From aa6bbfb7e7834587ec1d40de6b8e72ff4079a3a4 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Wed, 14 Aug 2019 11:35:11 -0500 Subject: [PATCH 01/45] Fix FLEXTableView table header behavior on iOS 13 --- Classes/ObjectExplorers/Views/FLEXTableView.m | 8 ++++---- FLEX.xcodeproj/project.pbxproj | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Classes/ObjectExplorers/Views/FLEXTableView.m b/Classes/ObjectExplorers/Views/FLEXTableView.m index afa9c08410..172b826b42 100644 --- a/Classes/ObjectExplorers/Views/FLEXTableView.m +++ b/Classes/ObjectExplorers/Views/FLEXTableView.m @@ -18,7 +18,7 @@ @implementation FLEXTableView - (CGFloat)_heightForHeaderInSection:(NSInteger)section { CGFloat height = [super _heightForHeaderInSection:section]; - if (section == 0 && self.tableHeaderView) { + if (section == 0 && self.tableHeaderView && !@available(iOS 13.0, *)) { return height - self.tableHeaderView.frame.size.height + 8; } @@ -30,9 +30,9 @@ - (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style self = [super initWithFrame:frame style:style]; if (self) { [self registerCells:@{ - self.defaultReuseIdentifier: [FLEXTableViewCell class], - self.subtitleReuseIdentifier: [FLEXSubtitleTableViewCell class], - self.multilineReuseIdentifier: [FLEXMultilineTableViewCell class], + self.defaultReuseIdentifier : [FLEXTableViewCell class], + self.subtitleReuseIdentifier : [FLEXSubtitleTableViewCell class], + self.multilineReuseIdentifier : [FLEXMultilineTableViewCell class], }]; } diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 19f3992365..4bf7fb9440 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -1251,6 +1251,7 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WARNING_CFLAGS = "-Wno-unsupported-availability-guard"; }; name = Debug; }; @@ -1304,6 +1305,7 @@ VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WARNING_CFLAGS = "-Wno-unsupported-availability-guard"; }; name = Release; }; From 78a34a84372a85a1307cfef8c54b13287964ef60 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Wed, 14 Aug 2019 11:50:53 -0500 Subject: [PATCH 02/45] Fix bug in FLEXArgumentInputObjectView Class was not properly detecting JSON encodable classes. We now parse class names out of the type encoding and turn them into Class objects to check where they fall in the class hierarchy. --- .../FLEXArgumentInputObjectView.m | 35 +++++++++++++------ .../FLEXArgumentInputStringView.m | 1 + .../Editing/FLEXDefaultEditorViewController.m | 10 ++++-- .../Editing/FLEXIvarEditorViewController.m | 3 ++ Classes/Utility/FLEXRuntimeUtility.h | 1 + 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m index 1f5b2fe484..881d6c7b1d 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m @@ -195,22 +195,35 @@ + (FLEXArgInputObjectType)preferredDefaultTypeForObjCType:(const char *)type wit if (strcmp(type, @encode(id)) != 0) { BOOL isJSONSerializableType = NO; + // Parse class name out of the string, + // which is in the form `@"ClassName"` + Class cls = NSClassFromString(({ + NSString *className = nil; + NSScanner *scan = [NSScanner scannerWithString:@(type)]; + NSCharacterSet *allowed = [NSCharacterSet + characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$" + ]; + + // Skip over the @" then scan the name + if ([scan scanString:@"@\"" intoString:nil]) { + [scan scanCharactersFromSet:allowed intoString:&className]; + } + + className; + })); + // Note: we can't use @encode(NSString) here because that drops // the class information and just goes to @encode(id). - NSArray *jsonTypes = @[ - @(FLEXEncodeClass(NSString)), - @(FLEXEncodeClass(NSNumber)), - @(FLEXEncodeClass(NSArray)), - @(FLEXEncodeClass(NSDictionary)), - @(FLEXEncodeClass(NSMutableString)), - @(FLEXEncodeClass(NSMutableArray)), - @(FLEXEncodeClass(NSMutableDictionary)), + NSArray *jsonTypes = @[ + [NSString class], + [NSNumber class], + [NSArray class], + [NSDictionary class], ]; // Look for matching types - NSString *typeStr = @(type); - for (NSString *encodedClass in jsonTypes) { - if ([typeStr isEqualToString:encodedClass]) { + for (Class jsonClass in jsonTypes) { + if ([cls isSubclassOfClass:jsonClass]) { isJSONSerializableType = YES; break; } diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m index 62a3c8c56d..f872f9d7c6 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m @@ -32,6 +32,7 @@ - (id)inputValue return [self.inputTextView.text length] > 0 ? [self.inputTextView.text copy] : nil; } +// TODO: Support using object address for strings, as in the object arg view. #pragma mark - diff --git a/Classes/Editing/FLEXDefaultEditorViewController.m b/Classes/Editing/FLEXDefaultEditorViewController.m index bc7f41d1b4..2839f14bb4 100644 --- a/Classes/Editing/FLEXDefaultEditorViewController.m +++ b/Classes/Editing/FLEXDefaultEditorViewController.m @@ -43,7 +43,10 @@ - (void)viewDidLoad self.fieldEditorView.fieldDescription = self.key; id currentValue = [self.defaults objectForKey:self.key]; - FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:@encode(id) currentValue:currentValue]; + FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory + argumentInputViewForTypeEncoding:FLEXEncodeObject(currentValue) + currentValue:currentValue + ]; inputView.backgroundColor = self.view.backgroundColor; inputView.inputValue = currentValue; self.fieldEditorView.argumentInputViews = @[inputView]; @@ -73,7 +76,10 @@ - (void)getterButtonPressed:(id)sender + (BOOL)canEditDefaultWithValue:(id)currentValue { - return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:@encode(id) currentValue:currentValue]; + return [FLEXArgumentInputViewFactory + canEditFieldWithTypeEncoding:FLEXEncodeObject(currentValue) + currentValue:currentValue + ]; } @end diff --git a/Classes/Editing/FLEXIvarEditorViewController.m b/Classes/Editing/FLEXIvarEditorViewController.m index 0a04f13ca8..a9aab92b03 100644 --- a/Classes/Editing/FLEXIvarEditorViewController.m +++ b/Classes/Editing/FLEXIvarEditorViewController.m @@ -52,6 +52,9 @@ - (void)viewDidLoad - (void)actionButtonPressed:(id)sender { [super actionButtonPressed:sender]; + + // TODO: check mutability and use mutableCopy if necessary; + // this currently could and would assign NSArray to NSMutableArray [FLEXRuntimeUtility setValue:self.firstInputView.inputValue forIvar:self.ivar onObject:self.target]; self.firstInputView.inputValue = [FLEXRuntimeUtility valueForIvar:self.ivar onObject:self.target]; diff --git a/Classes/Utility/FLEXRuntimeUtility.h b/Classes/Utility/FLEXRuntimeUtility.h index 5b28818864..7590f8a2c0 100644 --- a/Classes/Utility/FLEXRuntimeUtility.h +++ b/Classes/Utility/FLEXRuntimeUtility.h @@ -55,6 +55,7 @@ typedef NS_ENUM(char, FLEXTypeEncoding) }; #define FLEXEncodeClass(class) ("@\"" #class "\"") +#define FLEXEncodeObject(obj) (obj ? [NSString stringWithFormat:@"@\"%@\"", [obj class]].UTF8String : @encode(id)) @interface FLEXRuntimeUtility : NSObject From adf2fc56e857b71575f81fa516340983ca8bb736 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei <6d0847b9@opayq.com> Date: Fri, 16 Aug 2019 19:39:42 +0300 Subject: [PATCH 03/45] Add support for new UIScene APIs (#304) --- Classes/FLEXManager.h | 8 ++++++++ Classes/Manager/FLEXManager.m | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/Classes/FLEXManager.h b/Classes/FLEXManager.h index 3a542e230d..7e4a00d1e7 100644 --- a/Classes/FLEXManager.h +++ b/Classes/FLEXManager.h @@ -9,6 +9,10 @@ #import #import +#if !FLEX_AT_LEAST_IOS13_SDK +@class UIWindowScene; +#endif + typedef UIViewController *(^FLEXCustomContentViewerFuture)(NSData *data); @interface FLEXManager : NSObject @@ -21,6 +25,10 @@ typedef UIViewController *(^FLEXCustomContentViewerFuture)(NSData *data); - (void)hideExplorer; - (void)toggleExplorer; +/// Use this to present the explorer in a specific scene when the one +/// it chooses by default is not the one you wish to display it in. +- (void)showExplorerFromScene:(UIWindowScene *)scene API_AVAILABLE(ios(13.0)); + #pragma mark - Network Debugging /// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 957685603f..3131f696d3 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -7,6 +7,7 @@ // #import "FLEXManager.h" +#import "FLEXUtility.h" #import "FLEXExplorerViewController.h" #import "FLEXWindow.h" #import "FLEXGlobalsEntry.h" @@ -77,6 +78,21 @@ - (FLEXExplorerViewController *)explorerViewController - (void)showExplorer { self.explorerWindow.hidden = NO; +#if FLEX_AT_LEAST_IOS13_SDK + if (@available(iOS 13.0, *)) { + // Only look for a new scene if the one we have isn't the active scene + if (self.explorerWindow.windowScene.activationState != UISceneActivationStateForegroundActive) { + for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + // Look for an active UIWindowScene + if (scene.activationState == UISceneActivationStateForegroundActive && + [scene isKindOfClass:[UIWindowScene class]]) { + self.explorerWindow.windowScene = (UIWindowScene)scene; + break; + } + } + } + } +#endif } - (void)hideExplorer @@ -92,6 +108,16 @@ - (void)toggleExplorer { } } +#if FLEX_AT_LEAST_IOS13_SDK +- (void)showExplorerFromScene:(UIWindowScene *)scene +{ + if (@available(iOS 13.0, *)) { + self.explorerWindow.windowScene = scene; + } + self.explorerWindow.hidden = NO; +} +#endif + - (BOOL)isHidden { return self.explorerWindow.isHidden; From f2c8ede0e0e9da910487299f6ed578517ccd07e6 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Fri, 16 Aug 2019 11:58:24 -0500 Subject: [PATCH 04/45] Use dot syntax for properties Replaces the following method calls with dot syntax: - count, length, UTF8String, CGColor, contentOffset, firstObject, lastObject, allObjects, allKeys, allValues, subviews, scale, frame, bounds, bytes Also replaces various UIKit and Foundation singleton method calls with dot syntax, such as UIApplication.sharedApplication. These are all `class` properties now and Xcode will autocomplete them. Also fixes a couple warnings. --- Classes/Core/FLEXScopeCarousel.m | 8 +-- .../FLEXArgumentInputColorView.m | 18 +++---- .../FLEXArgumentInputFontsPickerView.m | 6 +-- .../FLEXArgumentInputNumberView.m | 2 +- .../FLEXArgumentInputStringView.m | 2 +- .../FLEXArgumentInputStructView.m | 6 +-- .../FLEXArgumentInputTextView.m | 4 +- .../FLEXArgumentInputView.m | 4 +- Classes/Editing/FLEXFieldEditorView.m | 2 +- .../Editing/FLEXFieldEditorViewController.m | 8 +-- .../FLEXPropertyEditorViewController.m | 4 +- .../FLEXExplorerViewController.m | 40 +++++++-------- Classes/ExplorerInterface/FLEXWindow.m | 2 +- .../FLEXMultiColumnTableView.m | 6 +-- .../FLEXSQLiteDatabaseManager.m | 4 +- .../DatabaseBrowser/FLEXTableColumnHeader.m | 2 +- .../DatabaseBrowser/FLEXTableContentCell.m | 6 +-- .../FLEXTableContentViewController.m | 4 +- .../DatabaseBrowser/FLEXTableLeftCell.m | 2 +- .../FLEXAddressExplorerCoordinator.m | 2 +- .../FLEXClassesTableViewController.m | 10 ++-- .../FLEXCookiesTableViewController.m | 4 +- .../FLEXInstancesTableViewController.m | 6 +-- .../FLEXLiveObjectsTableViewController.m | 4 +- .../FLEXWebViewController.m | 4 +- .../FLEXFileBrowserFileOperationController.m | 8 +-- .../FLEXFileBrowserSearchOperation.m | 8 +-- .../FLEXFileBrowserTableViewController.m | 24 ++++----- .../SystemLog/FLEXASLLogController.m | 2 +- .../SystemLog/FLEXOSLogController.h | 2 +- .../SystemLog/FLEXOSLogController.m | 2 +- .../SystemLog/FLEXSystemLogTableViewCell.m | 4 +- .../FLEXSystemLogTableViewController.m | 2 +- Classes/Manager/FLEXManager.m | 26 +++++----- Classes/Network/FLEXNetworkCurlLogger.m | 2 +- .../FLEXNetworkHistoryTableViewController.m | 22 ++++---- Classes/Network/FLEXNetworkRecorder.m | 14 +++--- .../FLEXNetworkSettingsTableViewController.m | 4 +- ...workTransactionDetailTableViewController.m | 40 +++++++-------- .../FLEXNetworkTransactionTableViewCell.m | 14 +++--- .../PonyDebugger/FLEXNetworkObserver.m | 16 +++--- .../FLEXArrayExplorerViewController.m | 4 +- .../FLEXBundleExplorerViewController.m | 2 +- .../FLEXColorExplorerViewController.m | 2 +- .../FLEXDictionaryExplorerViewController.m | 2 +- .../FLEXObjectExplorerViewController.m | 50 +++++++++---------- .../FLEXSetExplorerViewController.m | 2 +- .../FLEXObjectExplorerFactory.m | 20 ++++---- .../ObjectExplorers/Views/FLEXTableViewCell.m | 2 +- Classes/Toolbar/FLEXExplorerToolbar.m | 14 +++--- Classes/Toolbar/FLEXToolbarItem.m | 2 +- Classes/Utility/FLEXColor.m | 6 +-- .../Utility/FLEXKeyboardHelpViewController.m | 4 +- Classes/Utility/FLEXKeyboardShortcutManager.m | 8 +-- Classes/Utility/FLEXResources.m | 2 +- Classes/Utility/FLEXRuntimeUtility.m | 30 +++++------ Classes/Utility/FLEXUtility.h | 2 +- Classes/Utility/FLEXUtility.m | 22 ++++---- .../FLEXHierarchyTableViewCell.m | 4 +- .../FLEXHierarchyTableViewController.m | 6 +-- Example/UICatalog.xcodeproj/project.pbxproj | 5 +- .../AAPLActivityIndicatorViewController.m | 2 +- Example/UICatalog/AAPLAppDelegate.m | 12 ++--- Example/UICatalog/AAPLButtonViewController.m | 10 ++-- .../AAPLCatalogTableTableViewController.m | 2 +- .../AAPLCustomSearchBarViewController.m | 2 +- .../AAPLCustomToolbarViewController.m | 4 +- Example/UICatalog/AAPLImageViewController.m | 2 +- Example/UICatalog/AAPLMasterViewController.m | 2 +- .../UICatalog/AAPLPageControlViewController.m | 10 ++-- .../UICatalog/AAPLProgressViewController.m | 4 +- .../AAPLSegmentedControlViewController.m | 8 +-- Example/UICatalog/AAPLSliderViewController.m | 4 +- .../AAPLSplitViewControllerDelegate.m | 8 +-- Example/UICatalog/AAPLStepperViewController.m | 2 +- Example/UICatalog/AAPLSwitchViewController.m | 6 +-- .../UICatalog/AAPLTextFieldViewController.m | 8 +-- Example/UICatalog/AAPLTextViewController.m | 16 +++--- .../AAPLTintedToolbarViewController.m | 4 +- Example/UICatalog/AAPLWebViewController.m | 12 ++--- 80 files changed, 330 insertions(+), 327 deletions(-) diff --git a/Classes/Core/FLEXScopeCarousel.m b/Classes/Core/FLEXScopeCarousel.m index f6a5a5477a..43bbdb26eb 100644 --- a/Classes/Core/FLEXScopeCarousel.m +++ b/Classes/Core/FLEXScopeCarousel.m @@ -52,7 +52,7 @@ - (id)initWithFrame:(CGRect)frame { collectionViewLayout:layout ]; cv.showsHorizontalScrollIndicator = NO; - cv.backgroundColor = [UIColor clearColor]; + cv.backgroundColor = UIColor.clearColor; cv.delegate = self; cv.dataSource = self; [cv registerClass:[FLEXCarouselCell class] forCellWithReuseIdentifier:kCarouselCellReuseIdentifier]; @@ -68,7 +68,7 @@ - (id)initWithFrame:(CGRect)frame { // Dynamic type __weak __typeof(self) weakSelf = self; - _dynamicTypeObserver = [[NSNotificationCenter defaultCenter] + _dynamicTypeObserver = [NSNotificationCenter.defaultCenter addObserverForName:UIContentSizeCategoryDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) { [self.collectionView setNeedsLayout]; @@ -87,7 +87,7 @@ - (id)initWithFrame:(CGRect)frame { } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self.dynamicTypeObserver]; + [NSNotificationCenter.defaultCenter removeObserver:self.dynamicTypeObserver]; } #pragma mark - Overrides @@ -95,7 +95,7 @@ - (void)dealloc { - (void)drawRect:(CGRect)rect { [super drawRect:rect]; - CGFloat width = 1.f / [UIScreen mainScreen].scale; + CGFloat width = 1.f / UIScreen.mainScreen.scale; // Draw hairline CGContextRef context = UIGraphicsGetCurrentContext(); diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m index c12ab6945f..801ca7512d 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m @@ -107,12 +107,12 @@ - (id)initWithFrame:(CGRect)frame self = [super initWithFrame:frame]; if (self) { self.layer.borderWidth = 1.0; - self.layer.borderColor = [[UIColor blackColor] CGColor]; + self.layer.borderColor = UIColor.blackColor.CGColor; self.backgroundColor = [UIColor colorWithPatternImage:[[self class] backgroundPatternImage]]; self.colorOverlayView = [[UIView alloc] initWithFrame:self.bounds]; self.colorOverlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.colorOverlayView.backgroundColor = [UIColor clearColor]; + self.colorOverlayView.backgroundColor = UIColor.clearColor; [self addSubview:self.colorOverlayView]; } return self; @@ -134,12 +134,12 @@ + (UIImage *)backgroundPatternImage CGSize squareSize = CGSizeMake(kSquareDimension, kSquareDimension); CGSize imageSize = CGSizeMake(2.0 * kSquareDimension, 2.0 * kSquareDimension); - UIGraphicsBeginImageContextWithOptions(imageSize, YES, [[UIScreen mainScreen] scale]); + UIGraphicsBeginImageContextWithOptions(imageSize, YES, UIScreen.mainScreen.scale); - [[UIColor whiteColor] setFill]; + [UIColor.whiteColor setFill]; UIRectFill(CGRectMake(0, 0, imageSize.width, imageSize.height)); - [[UIColor grayColor] setFill]; + [UIColor.grayColor setFill]; UIRectFill(CGRectMake(squareSize.width, 0, squareSize.width, squareSize.height)); UIRectFill(CGRectMake(0, squareSize.height, squareSize.width, squareSize.height)); @@ -178,22 +178,22 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding [self addSubview:self.hexLabel]; self.alphaInput = [[FLEXColorComponentInputView alloc] init]; - self.alphaInput.slider.minimumTrackTintColor = [UIColor blackColor]; + self.alphaInput.slider.minimumTrackTintColor = UIColor.blackColor; self.alphaInput.delegate = self; [self addSubview:self.alphaInput]; self.redInput = [[FLEXColorComponentInputView alloc] init]; - self.redInput.slider.minimumTrackTintColor = [UIColor redColor]; + self.redInput.slider.minimumTrackTintColor = UIColor.redColor; self.redInput.delegate = self; [self addSubview:self.redInput]; self.greenInput = [[FLEXColorComponentInputView alloc] init]; - self.greenInput.slider.minimumTrackTintColor = [UIColor greenColor]; + self.greenInput.slider.minimumTrackTintColor = UIColor.greenColor; self.greenInput.delegate = self; [self addSubview:self.greenInput]; self.blueInput = [[FLEXColorComponentInputView alloc] init]; - self.blueInput.slider.minimumTrackTintColor = [UIColor blueColor]; + self.blueInput.slider.minimumTrackTintColor = UIColor.blueColor; self.blueInput.delegate = self; [self addSubview:self.blueInput]; } diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m index 5a665c5934..52d54e1700 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m @@ -40,7 +40,7 @@ - (void)setInputValue:(id)inputValue - (id)inputValue { - return [self.inputTextView.text length] > 0 ? [self.inputTextView.text copy] : nil; + return self.inputTextView.text.length > 0 ? [self.inputTextView.text copy] : nil; } #pragma mark - private @@ -74,7 +74,7 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - return [self.availableFonts count]; + return self.availableFonts.count; } #pragma mark - UIPickerViewDelegate @@ -84,7 +84,7 @@ - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forC UILabel *fontLabel; if (!view) { fontLabel = [UILabel new]; - fontLabel.backgroundColor = [UIColor clearColor]; + fontLabel.backgroundColor = UIColor.clearColor; fontLabel.textAlignment = NSTextAlignmentCenter; } else { fontLabel = (UILabel*)view; diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m index fafbe3a91b..e584f667c1 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m @@ -30,7 +30,7 @@ - (void)setInputValue:(id)inputValue - (id)inputValue { - return [FLEXRuntimeUtility valueForNumberWithObjCType:[self.typeEncoding UTF8String] fromInputString:self.inputTextView.text]; + return [FLEXRuntimeUtility valueForNumberWithObjCType:self.typeEncoding.UTF8String fromInputString:self.inputTextView.text]; } + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m index f872f9d7c6..3816e9e0f0 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m @@ -29,7 +29,7 @@ - (id)inputValue { // Interpret empty string as nil. We loose the ability to set empty string as a string value, // but we accept that tradeoff in exchange for not having to type quotes for every string. - return [self.inputTextView.text length] > 0 ? [self.inputTextView.text copy] : nil; + return self.inputTextView.text.length > 0 ? [self.inputTextView.text copy] : nil; } // TODO: Support using object address for strings, as in the object arg view. diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m index 30462b0ef1..897b1e11c2 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m @@ -30,7 +30,7 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding inputView.backgroundColor = self.backgroundColor; inputView.targetSize = FLEXArgumentInputViewSizeSmall; - if (fieldIndex < [customTitles count]) { + if (fieldIndex < customTitles.count) { inputView.title = customTitles[fieldIndex]; } else { inputView.title = [NSString stringWithFormat:@"%@ field %lu (%@)", structName, (unsigned long)fieldIndex, prettyTypeEncoding]; @@ -59,7 +59,7 @@ - (void)setInputValue:(id)inputValue { if ([inputValue isKindOfClass:[NSValue class]]) { const char *structTypeEncoding = [inputValue objCType]; - if (strcmp([self.typeEncoding UTF8String], structTypeEncoding) == 0) { + if (strcmp(self.typeEncoding.UTF8String, structTypeEncoding) == 0) { NSUInteger valueSize = 0; @try { // NSGetSizeAndAlignment barfs on type encoding for bitfields. @@ -90,7 +90,7 @@ - (void)setInputValue:(id)inputValue - (id)inputValue { NSValue *boxedStruct = nil; - const char *structTypeEncoding = [self.typeEncoding UTF8String]; + const char *structTypeEncoding = self.typeEncoding.UTF8String; NSUInteger structSize = 0; @try { // NSGetSizeAndAlignment barfs on type encoding for bitfields. diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m index 27ef526e7e..da7ddca630 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m @@ -27,7 +27,7 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding self.inputTextView = [UITextView new]; self.inputTextView.font = [[self class] inputFont]; self.inputTextView.backgroundColor = [FLEXColor primaryBackgroundColor]; - self.inputTextView.layer.borderColor = [[FLEXColor borderColor] CGColor]; + self.inputTextView.layer.borderColor = [FLEXColor borderColor].CGColor; self.inputTextView.layer.borderWidth = 1.f; self.inputTextView.layer.cornerRadius = 5.f; self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone; @@ -144,7 +144,7 @@ - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection #if FLEX_AT_LEAST_IOS13_SDK if (@available(iOS 13.0, *)) { if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) { - self.inputTextView.layer.borderColor = [[FLEXColor borderColor] CGColor]; + self.inputTextView.layer.borderColor = [FLEXColor borderColor].CGColor; } } #endif diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m index ed44ecdd74..9136916eb3 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m @@ -68,7 +68,7 @@ - (UILabel *)titleLabel - (BOOL)showsTitle { - return [self.title length] > 0; + return self.title.length > 0; } - (CGFloat)topInputFieldVerticalLayoutGuide @@ -114,7 +114,7 @@ - (CGSize)sizeThatFits:(CGSize)size { CGFloat height = 0; - if ([self.title length] > 0) { + if (self.title.length > 0) { CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX); height += ceil([self.titleLabel sizeThatFits:constrainSize].height); height += [[self class] titleBottomPadding]; diff --git a/Classes/Editing/FLEXFieldEditorView.m b/Classes/Editing/FLEXFieldEditorView.m index c037f59a3e..b8fb5ef68f 100644 --- a/Classes/Editing/FLEXFieldEditorView.m +++ b/Classes/Editing/FLEXFieldEditorView.m @@ -130,7 +130,7 @@ + (UIView *)dividerView + (UIColor *)dividerColor { - return [UIColor lightGrayColor]; + return UIColor.lightGrayColor; } + (CGFloat)horizontalPadding diff --git a/Classes/Editing/FLEXFieldEditorViewController.m b/Classes/Editing/FLEXFieldEditorViewController.m index 43dbaa166c..38b03e71e6 100644 --- a/Classes/Editing/FLEXFieldEditorViewController.m +++ b/Classes/Editing/FLEXFieldEditorViewController.m @@ -33,15 +33,15 @@ - (id)initWithTarget:(id)target self = [super initWithNibName:nil bundle:nil]; if (self) { self.target = target; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [NSNotificationCenter.defaultCenter removeObserver:self]; } - (void)keyboardDidShow:(NSNotification *)notification @@ -102,7 +102,7 @@ - (void)viewWillLayoutSubviews - (FLEXArgumentInputView *)firstInputView { - return [[self.fieldEditorView argumentInputViews] firstObject]; + return [self.fieldEditorView argumentInputViews].firstObject; } - (void)actionButtonPressed:(id)sender diff --git a/Classes/Editing/FLEXPropertyEditorViewController.m b/Classes/Editing/FLEXPropertyEditorViewController.m index 52737f2945..efa515ccb6 100644 --- a/Classes/Editing/FLEXPropertyEditorViewController.m +++ b/Classes/Editing/FLEXPropertyEditorViewController.m @@ -39,7 +39,7 @@ - (void)viewDidLoad id currentValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target]; self.setterButton.enabled = [[self class] canEditProperty:self.property onObject:self.target currentValue:currentValue]; - const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:self.property] UTF8String]; + const char *typeEncoding = [FLEXRuntimeUtility typeEncodingForProperty:self.property].UTF8String; FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:typeEncoding]; inputView.backgroundColor = self.view.backgroundColor; inputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target]; @@ -92,7 +92,7 @@ - (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputVi + (BOOL)canEditProperty:(objc_property_t)property onObject:(id)object currentValue:(id)value { - const char *typeEncoding = [[FLEXRuntimeUtility typeEncodingForProperty:property] UTF8String]; + const char *typeEncoding = [FLEXRuntimeUtility typeEncodingForProperty:property].UTF8String; BOOL canEditType = [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:value]; SEL setterSelector = [FLEXRuntimeUtility setterSelectorForProperty:property]; BOOL isReadonly = [FLEXRuntimeUtility isReadonlyProperty:property] && (!setterSelector || ![object respondsToSelector:setterSelector]); diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 056cb2f2dc..b5925f14a2 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -131,7 +131,7 @@ - (void)viewWillAppear:(BOOL)animated - (UIViewController *)viewControllerForRotationAndOrientation { - UIWindow *window = self.previousKeyWindow ?: [[UIApplication sharedApplication] keyWindow]; + UIWindow *window = self.previousKeyWindow ?: [UIApplication.sharedApplication keyWindow]; UIViewController *viewController = window.rootViewController; // Obfuscating selector _viewControllerForSupportedInterfaceOrientations NSString *viewControllerSelectorString = [@[@"_vie", @"wContro", @"llerFor", @"Supported", @"Interface", @"Orientations"] componentsJoinedByString:@""]; @@ -175,7 +175,7 @@ - (BOOL)shouldAutorotate - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [coordinator animateAlongsideTransition:^(id context) { - for (UIView *outlineView in [self.outlineViewsForVisibleViews allValues]) { + for (UIView *outlineView in self.outlineViewsForVisibleViews.allValues) { outlineView.hidden = YES; } self.selectedViewOverlay.hidden = YES; @@ -221,7 +221,7 @@ - (void)setSelectedView:(UIView *)selectedView } UIColor *outlineColor = [FLEXUtility consistentRandomColorForObject:selectedView]; self.selectedViewOverlay.backgroundColor = [outlineColor colorWithAlphaComponent:0.2]; - self.selectedViewOverlay.layer.borderColor = [outlineColor CGColor]; + self.selectedViewOverlay.layer.borderColor = outlineColor.CGColor; self.selectedViewOverlay.frame = [self.view convertRect:selectedView.bounds fromView:selectedView]; // Make sure the selected overlay is in front of all the other subviews except the toolbar, which should always stay on top. @@ -397,7 +397,7 @@ - (void)hierarchyButtonTapped:(FLEXToolbarItem *)sender - (UIWindow *)statusWindow { NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"]; - return [[UIApplication sharedApplication] valueForKey:statusBarString]; + return [UIApplication.sharedApplication valueForKey:statusBarString]; } - (void)moveButtonTapped:(FLEXToolbarItem *)sender @@ -562,8 +562,8 @@ - (UIView *)outlineViewForView:(UIView *)view { CGRect outlineFrame = [self frameInLocalCoordinatesForView:view]; UIView *outlineView = [[UIView alloc] initWithFrame:outlineFrame]; - outlineView.backgroundColor = [UIColor clearColor]; - outlineView.layer.borderColor = [[FLEXUtility consistentRandomColorForObject:view] CGColor]; + outlineView.backgroundColor = UIColor.clearColor; + outlineView.layer.borderColor = [FLEXUtility consistentRandomColorForObject:view].CGColor; outlineView.layer.borderWidth = 1.0; return outlineView; } @@ -594,7 +594,7 @@ - (UIView *)viewForSelectionAtPoint:(CGPoint)tapPointInWindow { // Select in the window that would handle the touch, but don't just use the result of hitTest:withEvent: so we can still select views with interaction disabled. // Default to the the application's key window if none of the windows want the touch. - UIWindow *windowForSelection = [[UIApplication sharedApplication] keyWindow]; + UIWindow *windowForSelection = [UIApplication.sharedApplication keyWindow]; for (UIWindow *window in [[FLEXUtility allWindows] reverseObjectEnumerator]) { // Ignore the explorer's own window. if (window != self.view.window) { @@ -606,7 +606,7 @@ - (UIView *)viewForSelectionAtPoint:(CGPoint)tapPointInWindow } // Select the deepest visible view at the tap point. This generally corresponds to what the user wants to select. - return [[self recursiveSubviewsAtPoint:tapPointInWindow inView:windowForSelection skipHiddenViews:YES] lastObject]; + return [self recursiveSubviewsAtPoint:tapPointInWindow inView:windowForSelection skipHiddenViews:YES].lastObject; } - (NSArray *)recursiveSubviewsAtPoint:(CGPoint)pointInView inView:(UIView *)view skipHiddenViews:(BOOL)skipHidden @@ -791,7 +791,7 @@ - (void)selectedViewExplorerFinished:(id)sender - (void)makeKeyAndPresentViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion { // Save the current key window so we can restore it following dismissal. - self.previousKeyWindow = [[UIApplication sharedApplication] keyWindow]; + self.previousKeyWindow = [UIApplication.sharedApplication keyWindow]; // Make our window key to correctly handle input. [self.view.window makeKeyWindow]; @@ -802,8 +802,8 @@ - (void)makeKeyAndPresentViewController:(UIViewController *)viewController anima // If this app doesn't use view controller based status bar management and we're on iOS 7+, // make sure the status bar style is UIStatusBarStyleDefault. We don't actually have to check // for view controller based management because the global methods no-op if that is turned on. - self.previousStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle]; - [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + self.previousStatusBarStyle = [UIApplication.sharedApplication statusBarStyle]; + [UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleDefault]; // Show the view controller. [self presentViewController:viewController animated:animated completion:completion]; @@ -821,7 +821,7 @@ - (void)resignKeyAndDismissViewControllerAnimated:(BOOL)animated completion:(voi [[self statusWindow] setWindowLevel:UIWindowLevelStatusBar]; // Restore the status bar style if the app is using global status bar management. - [[UIApplication sharedApplication] setStatusBarStyle:self.previousStatusBarStyle]; + [UIApplication.sharedApplication setStatusBarStyle:self.previousStatusBarStyle]; [self dismissViewControllerAnimated:animated completion:completion]; } @@ -885,7 +885,7 @@ - (void)toggleMenuTool [self toggleToolWithViewControllerProvider:^UIViewController *{ FLEXGlobalsTableViewController *globalsViewController = [[FLEXGlobalsTableViewController alloc] init]; globalsViewController.delegate = self; - [FLEXGlobalsTableViewController setApplicationWindow:[[UIApplication sharedApplication] keyWindow]]; + [FLEXGlobalsTableViewController setApplicationWindow:[UIApplication.sharedApplication keyWindow]]; return [[UINavigationController alloc] initWithRootViewController:globalsViewController]; } completion:nil]; } @@ -894,9 +894,9 @@ - (void)handleDownArrowKeyPressed { if (self.currentMode == FLEXExplorerModeMove) { CGRect frame = self.selectedView.frame; - frame.origin.y += 1.0 / [[UIScreen mainScreen] scale]; + frame.origin.y += 1.0 / UIScreen.mainScreen.scale; self.selectedView.frame = frame; - } else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) { + } else if (self.currentMode == FLEXExplorerModeSelect && self.viewsAtTapPoint.count > 0) { NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView]; if (selectedViewIndex > 0) { self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex - 1]; @@ -908,11 +908,11 @@ - (void)handleUpArrowKeyPressed { if (self.currentMode == FLEXExplorerModeMove) { CGRect frame = self.selectedView.frame; - frame.origin.y -= 1.0 / [[UIScreen mainScreen] scale]; + frame.origin.y -= 1.0 / UIScreen.mainScreen.scale; self.selectedView.frame = frame; - } else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) { + } else if (self.currentMode == FLEXExplorerModeSelect && self.viewsAtTapPoint.count > 0) { NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView]; - if (selectedViewIndex < [self.viewsAtTapPoint count] - 1) { + if (selectedViewIndex < self.viewsAtTapPoint.count - 1) { self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex + 1]; } } @@ -922,7 +922,7 @@ - (void)handleRightArrowKeyPressed { if (self.currentMode == FLEXExplorerModeMove) { CGRect frame = self.selectedView.frame; - frame.origin.x += 1.0 / [[UIScreen mainScreen] scale]; + frame.origin.x += 1.0 / UIScreen.mainScreen.scale; self.selectedView.frame = frame; } } @@ -931,7 +931,7 @@ - (void)handleLeftArrowKeyPressed { if (self.currentMode == FLEXExplorerModeMove) { CGRect frame = self.selectedView.frame; - frame.origin.x -= 1.0 / [[UIScreen mainScreen] scale]; + frame.origin.x -= 1.0 / UIScreen.mainScreen.scale; self.selectedView.frame = frame; } } diff --git a/Classes/ExplorerInterface/FLEXWindow.m b/Classes/ExplorerInterface/FLEXWindow.m index 810d5902d3..f74c8bdfc0 100644 --- a/Classes/ExplorerInterface/FLEXWindow.m +++ b/Classes/ExplorerInterface/FLEXWindow.m @@ -15,7 +15,7 @@ - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.backgroundColor = [UIColor clearColor]; + self.backgroundColor = UIColor.clearColor; // Some apps have windows at UIWindowLevelStatusBar + n. // If we make the window level too high, we block out UIAlertViews. // There's a balance between staying above the app's windows and staying below alerts. diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m index 7fa6bd7999..994ae3ba4e 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m @@ -204,7 +204,7 @@ - (void)loadLeftViewData - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UIColor *backgroundColor = [UIColor whiteColor]; + UIColor *backgroundColor = UIColor.whiteColor; if (indexPath.row % 2 != 0) { backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.750]; } @@ -219,11 +219,11 @@ - (UITableViewCell *)tableView:(UITableView *)tableView for (int i = 0 ; i < cell.labels.count; i++) { UILabel *label = cell.labels[i]; - label.textColor = [UIColor blackColor]; + label.textColor = UIColor.blackColor; NSString *content = [NSString stringWithFormat:@"%@",self.rowData[i]]; if ([content isEqualToString:@""]) { - label.textColor = [UIColor lightGrayColor]; + label.textColor = UIColor.lightGrayColor; content = @"NULL"; } label.text = content; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m index 46d92cab7c..561f4fbcde 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m @@ -33,7 +33,7 @@ - (BOOL)open { if (_db) { return YES; } - int err = sqlite3_open([_databasePath UTF8String], &_db); + int err = sqlite3_open(_databasePath.UTF8String, &_db); #if SQLITE_HAS_CODEC NSString *defaultSqliteDatabasePassword = [FLEXManager sharedManager].defaultSqliteDatabasePassword; @@ -117,7 +117,7 @@ - (BOOL)close { [self open]; NSMutableArray *> *resultArray = [NSMutableArray array]; sqlite3_stmt *pstmt; - if (sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pstmt, 0) == SQLITE_OK) { + if (sqlite3_prepare_v2(_db, sql.UTF8String, -1, &pstmt, 0) == SQLITE_OK) { while (sqlite3_step(pstmt) == SQLITE_ROW) { NSUInteger num_cols = (NSUInteger)sqlite3_data_count(pstmt); if (num_cols > 0) { diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m index fbe10a36a6..d8b7d015c4 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m @@ -18,7 +18,7 @@ - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.backgroundColor = [UIColor whiteColor]; + self.backgroundColor = UIColor.whiteColor; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, frame.size.width - 25, frame.size.height)]; label.font = [UIFont systemFontOfSize:13.0]; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.m index 339026cb86..fef9b89a32 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.m @@ -24,10 +24,10 @@ + (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteg NSMutableArray *labels = [NSMutableArray array]; for (int i = 0; i < number ; i++) { UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero]; - label.backgroundColor = [UIColor whiteColor]; + label.backgroundColor = UIColor.whiteColor; label.font = [UIFont systemFontOfSize:13.0]; label.textAlignment = NSTextAlignmentLeft; - label.backgroundColor = [UIColor greenColor]; + label.backgroundColor = UIColor.greenColor; [labels addObject:label]; UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:cell @@ -36,7 +36,7 @@ + (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteg label.userInteractionEnabled = YES; [cell.contentView addSubview:label]; - cell.contentView.backgroundColor = [UIColor whiteColor]; + cell.contentView.backgroundColor = UIColor.whiteColor; } cell.labels = labels; } diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m index 3199d75f80..92c0abdd54 100755 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m @@ -40,7 +40,7 @@ - (FLEXMultiColumnTableView *)multiColumnView { CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; _multiColumnView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin; - _multiColumnView.backgroundColor = [UIColor whiteColor]; + _multiColumnView.backgroundColor = UIColor.whiteColor; _multiColumnView.dataSource = self; _multiColumnView.delegate = self; } @@ -152,7 +152,7 @@ - (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderW }]; if (sortType == FLEXTableColumnHeaderSortTypeDesc) { NSEnumerator *contentReverseEnumerator = [sortContentData reverseObjectEnumerator]; - sortContentData = [NSArray arrayWithArray:[contentReverseEnumerator allObjects]]; + sortContentData = [NSArray arrayWithArray:contentReverseEnumerator.allObjects]; } self.contentsArray = sortContentData; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m index 199245fe28..33120b55a8 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m @@ -20,7 +20,7 @@ + (instancetype)cellWithTableView:(UITableView *)tableView UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero]; textLabel.textAlignment = NSTextAlignmentCenter; textLabel.font = [UIFont systemFontOfSize:13.0]; - textLabel.backgroundColor = [UIColor clearColor]; + textLabel.backgroundColor = UIColor.clearColor; [cell.contentView addSubview:textLabel]; cell.titlelabel = textLabel; } diff --git a/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m b/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m index 359a7e8736..a439c0c531 100644 --- a/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m +++ b/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m @@ -44,7 +44,7 @@ + (FLEXGlobalsTableViewControllerRowAction)globalsEntryRowAction:(FLEXGlobalsRow [host tryExploreAddress:address safely:action.style == UIAlertActionStyleDefault]; }; [addressInput addTextFieldWithConfigurationHandler:^(UITextField *textField) { - NSString *copied = [UIPasteboard generalPasteboard].string; + NSString *copied = UIPasteboard.generalPasteboard.string; textField.placeholder = @"0x00000070deadbeef"; // Go ahead and paste our clipboard if we have an address copied if ([copied hasPrefix:@"0x"]) { diff --git a/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m b/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m index edf6f3b676..b1a44acc3f 100644 --- a/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m @@ -46,7 +46,7 @@ - (void)setClassNames:(NSArray *)classNames - (void)loadClassNames { unsigned int classNamesCount = 0; - const char **classNames = objc_copyClassNamesForImage([self.binaryImageName UTF8String], &classNamesCount); + const char **classNames = objc_copyClassNamesForImage(self.binaryImageName.UTF8String, &classNamesCount); if (classNames) { NSMutableArray *classNameStrings = [NSMutableArray array]; for (unsigned int i = 0; i < classNamesCount; i++) { @@ -64,7 +64,7 @@ - (void)loadClassNames - (void)updateTitle { NSString *shortImageName = self.binaryImageName.lastPathComponent; - self.title = [NSString stringWithFormat:@"%@ Classes (%lu)", shortImageName, (unsigned long)[self.filteredClassNames count]]; + self.title = [NSString stringWithFormat:@"%@ Classes (%lu)", shortImageName, (unsigned long)self.filteredClassNames.count]; } @@ -86,7 +86,7 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - (void)updateSearchResults:(NSString *)searchText { - if ([searchText length] > 0) { + if (searchText.length > 0) { NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchText]; self.filteredClassNames = [self.classNames filteredArrayUsingPredicate:searchPredicate]; } else { @@ -106,7 +106,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.filteredClassNames count]; + return self.filteredClassNames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -130,7 +130,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *className = self.filteredClassNames[indexPath.row]; - Class selectedClass = objc_getClass([className UTF8String]); + Class selectedClass = objc_getClass(className.UTF8String); FLEXObjectExplorerViewController *objectExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:selectedClass]; [self.navigationController pushViewController:objectExplorer animated:YES]; } diff --git a/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m b/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m index f2f542aad3..2a01bd5789 100644 --- a/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m @@ -25,7 +25,7 @@ - (id)initWithStyle:(UITableViewStyle)style { self.title = @"Cookies"; NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)]; - _cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies sortedArrayUsingDescriptors:@[nameSortDescriptor]]; + _cookies = [NSHTTPCookieStorage.sharedHTTPCookieStorage.cookies sortedArrayUsingDescriptors:@[nameSortDescriptor]]; } return self; @@ -50,7 +50,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; - cell.detailTextLabel.textColor = [UIColor grayColor]; + cell.detailTextLabel.textColor = UIColor.grayColor; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } diff --git a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m index cd001588dd..9146094cb6 100644 --- a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m @@ -57,7 +57,7 @@ - (id)initWithReferences:(NSArray *)references + (instancetype)instancesTableViewControllerForClassName:(NSString *)className { - const char *classNameCString = [className UTF8String]; + const char *classNameCString = className.UTF8String; NSMutableArray *instances = [NSMutableArray array]; [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) { if (strcmp(classNameCString, class_getName(actualClass)) == 0) { @@ -71,7 +71,7 @@ + (instancetype)instancesTableViewControllerForClassName:(NSString *)className }]; NSArray *references = [FLEXObjectRef referencingAll:instances]; FLEXInstancesTableViewController *viewController = [[self alloc] initWithReferences:references]; - viewController.title = [NSString stringWithFormat:@"%@ (%lu)", className, (unsigned long)[instances count]]; + viewController.title = [NSString stringWithFormat:@"%@ (%lu)", className, (unsigned long)instances.count]; return viewController; } @@ -209,7 +209,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N UIFont *cellFont = [FLEXUtility defaultTableViewCellLabelFont]; cell.textLabel.font = cellFont; cell.detailTextLabel.font = cellFont; - cell.detailTextLabel.textColor = [UIColor grayColor]; + cell.detailTextLabel.textColor = UIColor.grayColor; } FLEXObjectRef *row = self.sections[indexPath.section][indexPath.row]; diff --git a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m index 7017f612d4..a9bbf76d40 100644 --- a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m @@ -45,7 +45,7 @@ - (void)viewDidLoad - (NSArray *)allClassNames { - return [self.instanceCountsForClassNames allKeys]; + return self.instanceCountsForClassNames.allKeys; } - (void)reloadTableData @@ -186,7 +186,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.filteredClassNames count]; + return self.filteredClassNames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/Classes/GlobalStateExplorers/FLEXWebViewController.m b/Classes/GlobalStateExplorers/FLEXWebViewController.m index dbaf842083..2080430eac 100644 --- a/Classes/GlobalStateExplorers/FLEXWebViewController.m +++ b/Classes/GlobalStateExplorers/FLEXWebViewController.m @@ -70,14 +70,14 @@ - (void)viewDidLoad self.webView.frame = self.view.bounds; self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - if ([self.originalText length] > 0) { + if (self.originalText.length > 0) { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:)]; } } - (void)copyButtonTapped:(id)sender { - [[UIPasteboard generalPasteboard] setString:self.originalText]; + [UIPasteboard.generalPasteboard setString:self.originalText]; } diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m index 4ed48f9a87..eca19450c7 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m @@ -39,7 +39,7 @@ - (instancetype)initWithPath:(NSString *)path - (void)show { BOOL isDirectory = NO; - BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory]; + BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:&isDirectory]; if (stillExists) { UIAlertView *deleteWarning = [[UIAlertView alloc] @@ -61,7 +61,7 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto if (buttonIndex == alertView.cancelButtonIndex) { // Nothing, just cancel } else if (buttonIndex == alertView.firstOtherButtonIndex) { - [[NSFileManager defaultManager] removeItemAtPath:self.path error:NULL]; + [NSFileManager.defaultManager removeItemAtPath:self.path error:NULL]; } } @@ -102,7 +102,7 @@ - (instancetype)initWithPath:(NSString *)path - (void)show { BOOL isDirectory = NO; - BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory]; + BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:&isDirectory]; if (stillExists) { UIAlertView *renameDialog = [[UIAlertView alloc] @@ -130,7 +130,7 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto } else if (buttonIndex == alertView.firstOtherButtonIndex) { NSString *newFileName = [alertView textFieldAtIndex:0].text; NSString *newPath = [[self.path stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName]; - [[NSFileManager defaultManager] moveItemAtPath:self.path toPath:newPath error:NULL]; + [NSFileManager.defaultManager moveItemAtPath:self.path toPath:newPath error:NULL]; } } diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m index 4b98c32239..0ac57271c8 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m @@ -17,7 +17,7 @@ - (void)flex_push:(id)anObject - (id)flex_pop { - id anObject = [self lastObject]; + id anObject = self.lastObject; [self removeLastObject]; return anObject; } @@ -37,7 +37,7 @@ @implementation FLEXFileBrowserSearchOperation - (uint64_t)totalSizeAtPath:(NSString *)path { - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSFileManager *fileManager = NSFileManager.defaultManager; NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL]; uint64_t totalSize = [attributes fileSize]; @@ -64,7 +64,7 @@ - (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString - (void)main { - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSFileManager *fileManager = NSFileManager.defaultManager; NSMutableArray *searchPaths = [NSMutableArray array]; NSMutableDictionary *sizeMapping = [NSMutableDictionary dictionary]; uint64_t totalSize = 0; @@ -72,7 +72,7 @@ - (void)main [stack flex_push:self.path]; //recursive found all match searchString paths, and precomputing there size - while ([stack count]) { + while (stack.count) { NSString *currentPath = [stack flex_pop]; NSArray *directoryPath = [fileManager contentsOfDirectoryAtPath:currentPath error:nil]; diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index 04607a0f4c..b01b8e49de 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -50,7 +50,7 @@ - (id)initWithPath:(NSString *)path //computing path size FLEXFileBrowserTableViewController *__weak weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSFileManager *fileManager = NSFileManager.defaultManager; NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL]; uint64_t totalSize = [attributes fileSize]; @@ -144,7 +144,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.searchController.isActive ? [self.searchPaths count] : [self.childPaths count]; + return self.searchController.isActive ? self.searchPaths.count : self.childPaths.count; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section @@ -160,17 +160,17 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInte sizeString = [NSByteCountFormatter stringFromByteCount:[currentSize longLongValue] countStyle:NSByteCountFormatterCountStyleFile]; } - return [NSString stringWithFormat:@"%lu files (%@)", (unsigned long)[currentPaths count], sizeString]; + return [NSString stringWithFormat:@"%lu files (%@)", (unsigned long)currentPaths.count, sizeString]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *fullPath = [self filePathAtIndexPath:indexPath]; - NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:NULL]; + NSDictionary *attributes = [NSFileManager.defaultManager attributesOfItemAtPath:fullPath error:NULL]; BOOL isDirectory = [attributes.fileType isEqual:NSFileTypeDirectory]; NSString *subtitle = nil; if (isDirectory) { - NSUInteger count = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:fullPath error:NULL] count]; + NSUInteger count = [NSFileManager.defaultManager contentsOfDirectoryAtPath:fullPath error:NULL].count; subtitle = [NSString stringWithFormat:@"%lu item%@", (unsigned long)count, (count == 1 ? @"" : @"s")]; } else { NSString *sizeString = [NSByteCountFormatter stringFromByteCount:attributes.fileSize countStyle:NSByteCountFormatterCountStyleFile]; @@ -189,7 +189,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell = [[FLEXFileBrowserTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; - cell.detailTextLabel.textColor = [UIColor grayColor]; + cell.detailTextLabel.textColor = UIColor.grayColor; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } NSString *cellTitle = [fullPath lastPathComponent]; @@ -213,7 +213,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath NSString *pathExtension = subpath.pathExtension; BOOL isDirectory = NO; - BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory]; + BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:fullPath isDirectory:&isDirectory]; UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; UIImage *image = cell.imageView.image; @@ -293,7 +293,7 @@ - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIn UIMenuItem *copyPath = [[UIMenuItem alloc] initWithTitle:@"Copy Path" action:@selector(fileBrowserCopyPath:)]; UIMenuItem *share = [[UIMenuItem alloc] initWithTitle:@"Share" action:@selector(fileBrowserShare:)]; - [UIMenuController sharedMenuController].menuItems = @[rename, delete, copyPath, share]; + UIMenuController.sharedMenuController.menuItems = @[rename, delete, copyPath, share]; return YES; } @@ -353,7 +353,7 @@ - (void)fileBrowserCopyPath:(UITableViewCell *)sender { NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; NSString *fullPath = [self filePathAtIndexPath:indexPath]; - [UIPasteboard generalPasteboard].string = fullPath; + UIPasteboard.generalPasteboard.string = fullPath; } - (void)fileBrowserShare:(UITableViewCell *)sender @@ -363,7 +363,7 @@ - (void)fileBrowserShare:(UITableViewCell *)sender NSURL *filePath = [NSURL fileURLWithPath:pathString]; BOOL isDirectory = NO; - [[NSFileManager defaultManager] fileExistsAtPath:pathString isDirectory:&isDirectory]; + [NSFileManager.defaultManager fileExistsAtPath:pathString isDirectory:&isDirectory]; if (isDirectory) { // UIDocumentInteractionController for folders @@ -388,7 +388,7 @@ - (void)reloadDisplayedPaths - (void)reloadCurrentPath { NSMutableArray *childPaths = [NSMutableArray array]; - NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL]; + NSArray *subpaths = [NSFileManager.defaultManager contentsOfDirectoryAtPath:self.path error:NULL]; for (NSString *subpath in subpaths) { [childPaths addObject:[self.path stringByAppendingPathComponent:subpath]]; } @@ -420,7 +420,7 @@ @implementation FLEXFileBrowserTableViewCell - (void)forwardAction:(SEL)action withSender:(id)sender { id target = [self.nextResponder targetForAction:action withSender:sender]; - [[UIApplication sharedApplication] sendAction:action to:target from:self forEvent:nil]; + [UIApplication.sharedApplication sendAction:action to:target from:self forEvent:nil]; } - (void)fileBrowserRename:(UIMenuController *)sender diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m index ed6fb0aceb..07a3cbd587 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m @@ -120,7 +120,7 @@ - (aslresponse)ASLMessageListForCurrentProcess { static NSString *pidString = nil; if (!pidString) { - pidString = @([[NSProcessInfo processInfo] processIdentifier]).stringValue; + pidString = @([NSProcessInfo.processInfo processIdentifier]).stringValue; } // Create system log query object. diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.h b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.h index 2e14779a5f..61311aca29 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.h +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.h @@ -8,7 +8,7 @@ #import "FLEXLogController.h" -#define FLEXOSLogAvailable() ([NSProcessInfo processInfo].operatingSystemVersion.majorVersion >= 10) +#define FLEXOSLogAvailable() (NSProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 10) extern NSString * const kFLEXiOSPersistentOSLogKey; diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m index 816b62517f..9548957595 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m @@ -73,7 +73,7 @@ - (id)init self = [super init]; if (self) { - _filterPid = [NSProcessInfo processInfo].processIdentifier; + _filterPid = NSProcessInfo.processInfo.processIdentifier; _levelInfo = NO; _subsystemInfo = NO; } diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m index da03c51575..84e80d7365 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m @@ -77,9 +77,9 @@ + (NSAttributedString *)attributedTextForLogMessage:(FLEXSystemLogMessage *)logM NSDictionary *attributes = @{ NSFontAttributeName : [UIFont fontWithName:@"CourierNewPSMT" size:12.0] }; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes]; - if ([highlightedText length] > 0) { + if (highlightedText.length > 0) { NSMutableAttributedString *mutableAttributedText = [attributedText mutableCopy]; - NSMutableDictionary *highlightAttributes = [@{ NSBackgroundColorAttributeName : [UIColor yellowColor] } mutableCopy]; + NSMutableDictionary *highlightAttributes = [@{ NSBackgroundColorAttributeName : UIColor.yellowColor } mutableCopy]; [highlightAttributes addEntriesFromDictionary:attributes]; NSRange remainingSearchRange = NSMakeRange(0, text.length); diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m index 09a179c2b6..06719d57e6 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m @@ -175,7 +175,7 @@ - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtInd { if (action == @selector(copy:)) { // We usually only want to copy the log message itself, not any metadata associated with it. - [UIPasteboard generalPasteboard].string = [self logMessageAtIndexPath:indexPath].messageText; + UIPasteboard.generalPasteboard.string = [self logMessageAtIndexPath:indexPath].messageText; } } diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 3131f696d3..3e2e038008 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -57,7 +57,7 @@ - (FLEXWindow *)explorerWindow NSAssert([NSThread isMainThread], @"You must use %@ from the main thread only.", NSStringFromClass([self class])); if (!_explorerWindow) { - _explorerWindow = [[FLEXWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + _explorerWindow = [[FLEXWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; _explorerWindow.eventDelegate = self; _explorerWindow.rootViewController = self.explorerViewController; } @@ -82,7 +82,7 @@ - (void)showExplorer if (@available(iOS 13.0, *)) { // Only look for a new scene if the one we have isn't the active scene if (self.explorerWindow.windowScene.activationState != UISceneActivationStateForegroundActive) { - for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { // Look for an active UIWindowScene if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { @@ -108,15 +108,15 @@ - (void)toggleExplorer { } } -#if FLEX_AT_LEAST_IOS13_SDK - (void)showExplorerFromScene:(UIWindowScene *)scene { + #if FLEX_AT_LEAST_IOS13_SDK if (@available(iOS 13.0, *)) { self.explorerWindow.windowScene = scene; } + #endif self.explorerWindow.hidden = NO; } -#endif - (BOOL)isHidden { @@ -328,7 +328,7 @@ - (void)setCustomViewerForContentType:(NSString *)contentType viewControllerFutu - (void)tryScrollDown { UIScrollView *firstScrollView = [self firstScrollView]; - CGPoint contentOffset = [firstScrollView contentOffset]; + CGPoint contentOffset = firstScrollView.contentOffset; CGFloat distance = floor(firstScrollView.frame.size.height / 2.0); CGFloat maxContentOffsetY = firstScrollView.contentSize.height + firstScrollView.contentInset.bottom - firstScrollView.frame.size.height; distance = MIN(maxContentOffsetY - firstScrollView.contentOffset.y, distance); @@ -339,7 +339,7 @@ - (void)tryScrollDown - (void)tryScrollUp { UIScrollView *firstScrollView = [self firstScrollView]; - CGPoint contentOffset = [firstScrollView contentOffset]; + CGPoint contentOffset = firstScrollView.contentOffset; CGFloat distance = floor(firstScrollView.frame.size.height / 2.0); CGFloat minContentOffsetY = -firstScrollView.contentInset.top; distance = MIN(firstScrollView.contentOffset.y - minContentOffsetY, distance); @@ -349,16 +349,16 @@ - (void)tryScrollUp - (UIScrollView *)firstScrollView { - NSMutableArray *views = [[[[UIApplication sharedApplication] keyWindow] subviews] mutableCopy]; + NSMutableArray *views = [UIApplication.sharedApplication.keyWindow.subviews mutableCopy]; UIScrollView *scrollView = nil; - while ([views count] > 0) { - UIView *view = [views firstObject]; + while (views.count > 0) { + UIView *view = views.firstObject; [views removeObjectAtIndex:0]; if ([view isKindOfClass:[UIScrollView class]]) { scrollView = (UIScrollView *)view; break; } else { - [views addObjectsFromArray:[view subviews]]; + [views addObjectsFromArray:view.subviews]; } } return scrollView; @@ -378,7 +378,7 @@ - (void)tryGoBack - (UIViewController *)topViewController { - UIViewController *topViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController]; + UIViewController *topViewController = [[UIApplication.sharedApplication keyWindow] rootViewController]; while ([topViewController presentedViewController]) { topViewController = [topViewController presentedViewController]; } @@ -388,7 +388,9 @@ - (UIViewController *)topViewController - (void)toggleTopViewControllerOfClass:(Class)class { UIViewController *topViewController = [self topViewController]; - if ([topViewController isKindOfClass:[UINavigationController class]] && [[[(UINavigationController *)topViewController viewControllers] firstObject] isKindOfClass:[class class]]) { + if ([topViewController isKindOfClass:[UINavigationController class]] && + [[(UINavigationController *)topViewController viewControllers].firstObject isKindOfClass:[class class]]) + { [[topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; } else { id viewController = [[class alloc] init]; diff --git a/Classes/Network/FLEXNetworkCurlLogger.m b/Classes/Network/FLEXNetworkCurlLogger.m index a67b25accf..2bc6088d8f 100644 --- a/Classes/Network/FLEXNetworkCurlLogger.m +++ b/Classes/Network/FLEXNetworkCurlLogger.m @@ -18,7 +18,7 @@ + (NSString *)curlCommandString:(NSURLRequest *)request { [curlCommandString appendFormat:@"-H \'%@: %@\' ", key, val]; }]; - NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL]; + NSArray *cookies = [NSHTTPCookieStorage.sharedHTTPCookieStorage cookiesForURL:request.URL]; if (cookies) { [curlCommandString appendFormat:@"-H \'Cookie:"]; for (NSHTTPCookie *cookie in cookies) { diff --git a/Classes/Network/FLEXNetworkHistoryTableViewController.m b/Classes/Network/FLEXNetworkHistoryTableViewController.m index 802fefe8df..a031f5854d 100644 --- a/Classes/Network/FLEXNetworkHistoryTableViewController.m +++ b/Classes/Network/FLEXNetworkHistoryTableViewController.m @@ -34,10 +34,10 @@ - (id)init { self = [super initWithStyle:UITableViewStylePlain]; if (self) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNewTransactionRecordedNotification:) name:kFLEXNetworkRecorderNewTransactionNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionsClearedNotification:) name:kFLEXNetworkRecorderTransactionsClearedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNetworkObserverEnabledStateChangedNotification:) name:kFLEXNetworkObserverEnabledStateChangedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleNewTransactionRecordedNotification:) name:kFLEXNetworkRecorderNewTransactionNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleTransactionsClearedNotification:) name:kFLEXNetworkRecorderTransactionsClearedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleNetworkObserverEnabledStateChangedNotification:) name:kFLEXNetworkObserverEnabledStateChangedNotification object:nil]; self.title = @"📡 Network"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStylePlain target:self action:@selector(settingsButtonTapped:)]; @@ -50,7 +50,7 @@ - (id)init - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [NSNotificationCenter.defaultCenter removeObserver:self]; } - (void)viewDidLoad @@ -140,10 +140,10 @@ - (NSString *)headerText NSInteger totalRequests = 0; if (self.searchController.isActive) { bytesReceived = self.filteredBytesReceived; - totalRequests = [self.filteredNetworkTransactions count]; + totalRequests = self.filteredNetworkTransactions.count; } else { bytesReceived = self.bytesReceived; - totalRequests = [self.networkTransactions count]; + totalRequests = self.networkTransactions.count; } NSString *byteCountText = [NSByteCountFormatter stringFromByteCount:bytesReceived countStyle:NSByteCountFormatterCountStyleBinary]; NSString *requestsText = totalRequests == 1 ? @"Request" : @"Requests"; @@ -185,9 +185,9 @@ - (void)tryUpdateTransactions return; } - NSInteger existingRowCount = [self.networkTransactions count]; + NSInteger existingRowCount = self.networkTransactions.count; [self updateTransactions]; - NSInteger newRowCount = [self.networkTransactions count]; + NSInteger newRowCount = self.networkTransactions.count; NSInteger addedRowCount = newRowCount - existingRowCount; if (addedRowCount != 0 && !self.isPresentingSearch) { @@ -259,7 +259,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.searchController.isActive ? [self.filteredNetworkTransactions count] : [self.networkTransactions count]; + return self.searchController.isActive ? self.filteredNetworkTransactions.count : self.networkTransactions.count; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section @@ -315,7 +315,7 @@ - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtInd if (action == @selector(copy:)) { FLEXNetworkTransaction *transaction = [self transactionAtIndexPath:indexPath inTableView:tableView]; NSString *requestURLString = transaction.request.URL.absoluteString ?: @""; - [[UIPasteboard generalPasteboard] setString:requestURLString]; + [UIPasteboard.generalPasteboard setString:requestURLString]; } } diff --git a/Classes/Network/FLEXNetworkRecorder.m b/Classes/Network/FLEXNetworkRecorder.m index 58843351c7..898eada888 100644 --- a/Classes/Network/FLEXNetworkRecorder.m +++ b/Classes/Network/FLEXNetworkRecorder.m @@ -95,7 +95,7 @@ - (void)clearRecordedActivity [self.orderedTransactions removeAllObjects]; [self.networkTransactionsForRequestIdentifiers removeAllObjects]; dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderTransactionsClearedNotification object:self]; + [NSNotificationCenter.defaultCenter postNotificationName:kFLEXNetworkRecorderTransactionsClearedNotification object:self]; }); }); } @@ -173,7 +173,7 @@ - (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(N transaction.transactionState = FLEXNetworkTransactionStateFinished; transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate]; - BOOL shouldCache = [responseBody length] > 0; + BOOL shouldCache = responseBody.length > 0; if (!self.shouldCacheMediaResponses) { NSArray *ignoredMIMETypePrefixes = @[ @"audio", @"image", @"video" ]; for (NSString *ignoredPrefix in ignoredMIMETypePrefixes) { @@ -182,14 +182,14 @@ - (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(N } if (shouldCache) { - [self.responseCache setObject:responseBody forKey:requestID cost:[responseBody length]]; + [self.responseCache setObject:responseBody forKey:requestID cost:responseBody.length]; } NSString *mimeType = transaction.response.MIMEType; - if ([mimeType hasPrefix:@"image/"] && [responseBody length] > 0) { + if ([mimeType hasPrefix:@"image/"] && responseBody.length > 0) { // Thumbnail image previews on a separate background queue dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSInteger maxPixelDimension = [[UIScreen mainScreen] scale] * 32.0; + NSInteger maxPixelDimension = UIScreen.mainScreen.scale * 32.0; transaction.responseThumbnail = [FLEXUtility thumbnailedImageWithMaxPixelDimension:maxPixelDimension fromImageData:responseBody]; [self postUpdateNotificationForTransaction:transaction]; }); @@ -253,7 +253,7 @@ - (void)postNewTransactionNotificationWithTransaction:(FLEXNetworkTransaction *) { dispatch_async(dispatch_get_main_queue(), ^{ NSDictionary *userInfo = @{ kFLEXNetworkRecorderUserInfoTransactionKey : transaction }; - [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderNewTransactionNotification object:self userInfo:userInfo]; + [NSNotificationCenter.defaultCenter postNotificationName:kFLEXNetworkRecorderNewTransactionNotification object:self userInfo:userInfo]; }); } @@ -261,7 +261,7 @@ - (void)postUpdateNotificationForTransaction:(FLEXNetworkTransaction *)transacti { dispatch_async(dispatch_get_main_queue(), ^{ NSDictionary *userInfo = @{ kFLEXNetworkRecorderUserInfoTransactionKey : transaction }; - [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkRecorderTransactionUpdatedNotification object:self userInfo:userInfo]; + [NSNotificationCenter.defaultCenter postNotificationName:kFLEXNetworkRecorderTransactionUpdatedNotification object:self userInfo:userInfo]; }); } diff --git a/Classes/Network/FLEXNetworkSettingsTableViewController.m b/Classes/Network/FLEXNetworkSettingsTableViewController.m index a3da45a2cf..d8791c54e8 100644 --- a/Classes/Network/FLEXNetworkSettingsTableViewController.m +++ b/Classes/Network/FLEXNetworkSettingsTableViewController.m @@ -87,7 +87,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.cells count]; + return self.cells.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -134,7 +134,7 @@ - (UITableViewCell *)buttonCellWithTitle:(NSString *)title touchUpAction:(SEL)ac UIButton *actionButton = [UIButton buttonWithType:UIButtonTypeSystem]; [actionButton setTitle:title forState:UIControlStateNormal]; if (isDestructive) { - actionButton.tintColor = [UIColor redColor]; + actionButton.tintColor = UIColor.redColor; } actionButton.titleLabel.font = [[self class] cellTitleFont]; [actionButton addTarget:self action:@selector(clearRequestsTapped:) forControlEvents:UIControlEventTouchUpInside]; diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m index a4b924d4f3..988675b904 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m @@ -55,7 +55,7 @@ - (instancetype)initWithStyle:(UITableViewStyle)style // Force grouped style self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy curl" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonPressed:)]; } return self; @@ -90,23 +90,23 @@ - (void)rebuildTableSections NSMutableArray *sections = [NSMutableArray array]; FLEXNetworkDetailSection *generalSection = [[self class] generalSectionForTransaction:self.transaction]; - if ([generalSection.rows count] > 0) { + if (generalSection.rows.count > 0) { [sections addObject:generalSection]; } FLEXNetworkDetailSection *requestHeadersSection = [[self class] requestHeadersSectionForTransaction:self.transaction]; - if ([requestHeadersSection.rows count] > 0) { + if (requestHeadersSection.rows.count > 0) { [sections addObject:requestHeadersSection]; } FLEXNetworkDetailSection *queryParametersSection = [[self class] queryParametersSectionForTransaction:self.transaction]; - if ([queryParametersSection.rows count] > 0) { + if (queryParametersSection.rows.count > 0) { [sections addObject:queryParametersSection]; } FLEXNetworkDetailSection *postBodySection = [[self class] postBodySectionForTransaction:self.transaction]; - if ([postBodySection.rows count] > 0) { + if (postBodySection.rows.count > 0) { [sections addObject:postBodySection]; } FLEXNetworkDetailSection *responseHeadersSection = [[self class] responseHeadersSectionForTransaction:self.transaction]; - if ([responseHeadersSection.rows count] > 0) { + if (responseHeadersSection.rows.count > 0) { [sections addObject:responseHeadersSection]; } @@ -123,20 +123,20 @@ - (void)handleTransactionUpdatedNotification:(NSNotification *)notification - (void)copyButtonPressed:(id)sender { - [[UIPasteboard generalPasteboard] setString:[FLEXNetworkCurlLogger curlCommandString:_transaction.request]]; + [UIPasteboard.generalPasteboard setString:[FLEXNetworkCurlLogger curlCommandString:_transaction.request]]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [self.sections count]; + return self.sections.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { FLEXNetworkDetailSection *sectionModel = self.sections[section]; - return [sectionModel.rows count]; + return sectionModel.rows.count; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section @@ -204,7 +204,7 @@ - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtInd { if (action == @selector(copy:)) { FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath]; - [[UIPasteboard generalPasteboard] setString:row.detailText]; + [UIPasteboard.generalPasteboard setString:row.detailText]; } } @@ -248,10 +248,10 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti requestMethodRow.detailText = transaction.request.HTTPMethod; [rows addObject:requestMethodRow]; - if ([transaction.cachedRequestBody length] > 0) { + if (transaction.cachedRequestBody.length > 0) { FLEXNetworkDetailRow *postBodySizeRow = [[FLEXNetworkDetailRow alloc] init]; postBodySizeRow.title = @"Request Body Size"; - postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:[transaction.cachedRequestBody length] countStyle:NSByteCountFormatterCountStyleBinary]; + postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.cachedRequestBody.length countStyle:NSByteCountFormatterCountStyleBinary]; [rows addObject:postBodySizeRow]; FLEXNetworkDetailRow *postBodyRow = [[FLEXNetworkDetailRow alloc] init]; @@ -272,7 +272,7 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti } NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:transaction.response]; - if ([statusCodeString length] > 0) { + if (statusCodeString.length > 0) { FLEXNetworkDetailRow *statusCodeRow = [[FLEXNetworkDetailRow alloc] init]; statusCodeRow.title = @"Status Code"; statusCodeRow.detailText = statusCodeString; @@ -289,7 +289,7 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti FLEXNetworkDetailRow *responseBodyRow = [[FLEXNetworkDetailRow alloc] init]; responseBodyRow.title = @"Response Body"; NSData *responseData = [[FLEXNetworkRecorder defaultRecorder] cachedResponseBodyForTransaction:transaction]; - if ([responseData length] > 0) { + if (responseData.length > 0) { responseBodyRow.detailText = @"tap to view"; // Avoid a long lived strong reference to the response data in case we need to purge it from the cache. __weak NSData *weakResponseData = responseData; @@ -380,7 +380,7 @@ + (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransact { FLEXNetworkDetailSection *postBodySection = [[FLEXNetworkDetailSection alloc] init]; postBodySection.title = @"Request Body Parameters"; - if ([transaction.cachedRequestBody length] > 0) { + if (transaction.cachedRequestBody.length > 0) { NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; if ([contentType hasPrefix:@"application/x-www-form-urlencoded"]) { NSString *bodyString = [[NSString alloc] initWithData:[self postBodyDataForTransaction:transaction] encoding:NSUTF8StringEncoding]; @@ -413,8 +413,8 @@ + (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkT + (NSArray *)networkDetailRowsFromDictionary:(NSDictionary *)dictionary { - NSMutableArray *rows = [NSMutableArray arrayWithCapacity:[dictionary count]]; - NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSMutableArray *rows = [NSMutableArray arrayWithCapacity:dictionary.count]; + NSArray *sortedKeys = [dictionary.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; for (NSString *key in sortedKeys) { id value = dictionary[key]; FLEXNetworkDetailRow *row = [[FLEXNetworkDetailRow alloc] init]; @@ -441,7 +441,7 @@ + (UIViewController *)detailViewControllerForMIMEType:(NSString *)mimeType data: UIViewController *detailViewController = nil; if ([FLEXUtility isValidJSONData:data]) { NSString *prettyJSON = [FLEXUtility prettyJSONStringFromData:data]; - if ([prettyJSON length] > 0) { + if (prettyJSON.length > 0) { detailViewController = [[FLEXWebViewController alloc] initWithText:prettyJSON]; } } else if ([mimeType hasPrefix:@"image/"]) { @@ -455,7 +455,7 @@ + (UIViewController *)detailViewControllerForMIMEType:(NSString *)mimeType data: // Fall back to trying to show the response as text if (!detailViewController) { NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if ([text length] > 0) { + if (text.length > 0) { detailViewController = [[FLEXWebViewController alloc] initWithText:text]; } } @@ -465,7 +465,7 @@ + (UIViewController *)detailViewControllerForMIMEType:(NSString *)mimeType data: + (NSData *)postBodyDataForTransaction:(FLEXNetworkTransaction *)transaction { NSData *bodyData = transaction.cachedRequestBody; - if ([bodyData length] > 0) { + if (bodyData.length > 0) { NSString *contentEncoding = [transaction.request valueForHTTPHeaderField:@"Content-Encoding"]; if ([contentEncoding rangeOfString:@"deflate" options:NSCaseInsensitiveSearch].length > 0 || [contentEncoding rangeOfString:@"gzip" options:NSCaseInsensitiveSearch].length > 0) { bodyData = [FLEXUtility inflatedDataFromCompressedData:bodyData]; diff --git a/Classes/Network/FLEXNetworkTransactionTableViewCell.m b/Classes/Network/FLEXNetworkTransactionTableViewCell.m index 89895e053a..63688e21aa 100644 --- a/Classes/Network/FLEXNetworkTransactionTableViewCell.m +++ b/Classes/Network/FLEXNetworkTransactionTableViewCell.m @@ -41,7 +41,7 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStr [self.contentView addSubview:self.pathLabel]; self.thumbnailImageView = [[UIImageView alloc] init]; - self.thumbnailImageView.layer.borderColor = [[UIColor blackColor] CGColor]; + self.thumbnailImageView.layer.borderColor = UIColor.blackColor.CGColor; self.thumbnailImageView.layer.borderWidth = 1.0; self.thumbnailImageView.contentMode = UIViewContentModeScaleAspectFit; [self.contentView addSubview:self.thumbnailImageView]; @@ -80,7 +80,7 @@ - (void)layoutSubviews self.nameLabel.text = [self nameLabelText]; CGSize nameLabelPreferredSize = [self.nameLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)]; self.nameLabel.frame = CGRectMake(textOriginX, kVerticalPadding, availableTextWidth, nameLabelPreferredSize.height); - self.nameLabel.textColor = (self.transaction.error || [FLEXUtility isErrorStatusCodeFromURLResponse:self.transaction.response]) ? [UIColor redColor] : [FLEXColor primaryTextColor]; + self.nameLabel.textColor = (self.transaction.error || [FLEXUtility isErrorStatusCodeFromURLResponse:self.transaction.response]) ? UIColor.redColor : [FLEXColor primaryTextColor]; self.pathLabel.text = [self pathLabelText]; CGSize pathLabelPreferredSize = [self.pathLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)]; @@ -99,7 +99,7 @@ - (NSString *)nameLabelText { NSURL *url = self.transaction.request.URL; NSString *name = [url lastPathComponent]; - if ([name length] == 0) { + if (name.length == 0) { name = @"/"; } NSString *query = [url query]; @@ -113,7 +113,7 @@ - (NSString *)pathLabelText { NSURL *url = self.transaction.request.URL; NSMutableArray *mutablePathComponents = [[url pathComponents] mutableCopy]; - if ([mutablePathComponents count] > 0) { + if (mutablePathComponents.count > 0) { [mutablePathComponents removeLastObject]; } NSString *path = [url host]; @@ -128,19 +128,19 @@ - (NSString *)transactionDetailsLabelText NSMutableArray *detailComponents = [NSMutableArray array]; NSString *timestamp = [[self class] timestampStringFromRequestDate:self.transaction.startTime]; - if ([timestamp length] > 0) { + if (timestamp.length > 0) { [detailComponents addObject:timestamp]; } // Omit method for GET (assumed as default) NSString *httpMethod = self.transaction.request.HTTPMethod; - if ([httpMethod length] > 0) { + if (httpMethod.length > 0) { [detailComponents addObject:httpMethod]; } if (self.transaction.transactionState == FLEXNetworkTransactionStateFinished || self.transaction.transactionState == FLEXNetworkTransactionStateFailed) { NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:self.transaction.response]; - if ([statusCodeString length] > 0) { + if (statusCodeString.length > 0) { [detailComponents addObject:statusCodeString]; } diff --git a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m index 8438edc589..a57b8b446d 100644 --- a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m +++ b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m @@ -90,7 +90,7 @@ + (void)setEnabled:(BOOL)enabled } if (previouslyEnabled != enabled) { - [[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkObserverEnabledStateChangedNotification object:self]; + [NSNotificationCenter.defaultCenter postNotificationName:kFLEXNetworkObserverEnabledStateChangedNotification object:self]; } } @@ -280,9 +280,9 @@ + (void)injectIntoNSURLSessionTaskResume // In iOS 8 resume lives in NSURLSessionTask // In iOS 9 resume lives in __NSCFURLSessionTask Class class = Nil; - if (![[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { + if (![NSProcessInfo.processInfo respondsToSelector:@selector(operatingSystemVersion)]) { class = NSClassFromString([@[@"__", @"NSC", @"FLocalS", @"ession", @"Task"] componentsJoinedByString:@""]); - } else if ([[NSProcessInfo processInfo] operatingSystemVersion].majorVersion < 9) { + } else if ([NSProcessInfo.processInfo operatingSystemVersion].majorVersion < 9) { class = [NSURLSessionTask class]; } else { class = NSClassFromString([@[@"__", @"NSC", @"FURLS", @"ession", @"Task"] componentsJoinedByString:@""]); @@ -322,7 +322,7 @@ + (void)injectIntoNSURLConnectionAsynchronousClassMethod [[FLEXNetworkRecorder defaultRecorder] recordMechanism:mechanism forRequestID:requestID]; NSURLConnectionAsyncCompletion completionWrapper = ^(NSURLResponse *response, NSData *data, NSError *connectionError) { [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:response]; - [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]]; + [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:data.length]; if (connectionError) { [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:connectionError]; } else { @@ -363,7 +363,7 @@ + (void)injectIntoNSURLConnectionSynchronousClassMethod NSURLResponse *temporaryResponse = nil; data = ((id(*)(id, SEL, id, NSURLResponse **, NSError **))objc_msgSend)(slf, swizzledSelector, request, &temporaryResponse, &temporaryError); [[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:temporaryResponse]; - [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]]; + [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:data.length]; if (temporaryError) { [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:temporaryError]; } else { @@ -410,7 +410,7 @@ + (void)injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) { // iOS 7 does not implement these methods on NSURLSession. We actually want to // swizzle __NSCFURLSession, which we can get from the class of the shared session - class = [[NSURLSession sharedSession] class]; + class = [NSURLSession.sharedSession class]; } NSURLSessionTask *(^asyncDataOrDownloadSwizzleBlock)(Class, id, NSURLSessionAsyncCompletion) = ^NSURLSessionTask *(Class slf, id argument, NSURLSessionAsyncCompletion completion) { @@ -457,7 +457,7 @@ + (void)injectIntoNSURLSessionAsyncUploadTaskMethods if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) { // iOS 7 does not implement these methods on NSURLSession. We actually want to // swizzle __NSCFURLSession, which we can get from the class of the shared session - class = [[NSURLSession sharedSession] class]; + class = [NSURLSession.sharedSession class]; } NSURLSessionUploadTask *(^asyncUploadTaskSwizzleBlock)(Class, NSURLRequest *, id, NSURLSessionAsyncCompletion) = ^NSURLSessionUploadTask *(Class slf, NSURLRequest *request, id argument, NSURLSessionAsyncCompletion completion) { @@ -495,7 +495,7 @@ + (NSURLSessionAsyncCompletion)asyncCompletionWrapperForRequestID:(NSString *)re } else if ([fileURLOrData isKindOfClass:[NSData class]]) { data = fileURLOrData; } - [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:[data length]]; + [[FLEXNetworkRecorder defaultRecorder] recordDataReceivedWithRequestID:requestID dataLength:data.length]; if (error) { [[FLEXNetworkRecorder defaultRecorder] recordLoadingFailedWithRequestID:requestID error:error]; } else { diff --git a/Classes/ObjectExplorers/Controllers/FLEXArrayExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXArrayExplorerViewController.m index b53ce5dd7c..6843347932 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXArrayExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXArrayExplorerViewController.m @@ -34,8 +34,8 @@ - (NSString *)customSectionTitle - (NSArray *)customSectionRowCookies { // Use index numbers as the row cookies - NSMutableArray *cookies = [NSMutableArray arrayWithCapacity:[self.array count]]; - for (NSUInteger i = 0; i < [self.array count]; i++) { + NSMutableArray *cookies = [NSMutableArray arrayWithCapacity:self.array.count]; + for (NSUInteger i = 0; i < self.array.count; i++) { [cookies addObject:@(i)]; } return cookies; diff --git a/Classes/ObjectExplorers/Controllers/FLEXBundleExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXBundleExplorerViewController.m index e6083124f0..76f46ff13e 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXBundleExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXBundleExplorerViewController.m @@ -34,7 +34,7 @@ - (NSArray *)customSectionRowCookies { BOOL isDirectory = NO; NSString *bundlePath = self.bundleToExplore.bundlePath; - if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath isDirectory:&isDirectory] && isDirectory) { + if ([NSFileManager.defaultManager fileExistsAtPath:bundlePath isDirectory:&isDirectory] && isDirectory) { return [@[@(FLEXBundleExplorerRowBundlePath)] arrayByAddingObjectsFromArray:[super customSectionRowCookies]]; } diff --git a/Classes/ObjectExplorers/Controllers/FLEXColorExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXColorExplorerViewController.m index 59687898bd..758930e57c 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXColorExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXColorExplorerViewController.m @@ -42,7 +42,7 @@ - (NSArray *)customSectionRowCookies - (UIView *)customViewForRowCookie:(id)rowCookie { if ([rowCookie isKindOfClass:[NSNumber class]]) { - CGFloat width = [UIScreen mainScreen].bounds.size.width; + CGFloat width = UIScreen.mainScreen.bounds.size.width; switch ([rowCookie integerValue]) { case 0: { UIView *square = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)]; diff --git a/Classes/ObjectExplorers/Controllers/FLEXDictionaryExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXDictionaryExplorerViewController.m index c1f5ca5998..d34fad32e5 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXDictionaryExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXDictionaryExplorerViewController.m @@ -33,7 +33,7 @@ - (NSString *)customSectionTitle - (NSArray *)customSectionRowCookies { - return [self.dictionary allKeys]; + return self.dictionary.allKeys; } - (NSString *)customSectionTitleForRowCookie:(id)rowCookie diff --git a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m index c93884c7f8..53d725309e 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m @@ -78,8 +78,8 @@ + (void)initialize if (self == [FLEXObjectExplorerViewController class]) { // Initialize custom menu items for entire app UIMenuItem *copyObjectAddress = [[UIMenuItem alloc] initWithTitle:@"Copy Address" action:@selector(copyObjectAddress:)]; - [UIMenuController sharedMenuController].menuItems = @[copyObjectAddress]; - [[UIMenuController sharedMenuController] update]; + UIMenuController.sharedMenuController.menuItems = @[copyObjectAddress]; + [UIMenuController.sharedMenuController update]; } } @@ -187,7 +187,7 @@ - (void)setObject:(id)object self.title = [[object class] description]; // Only refresh if the view has appeared - #warning TODO make .object readonly so we don't have to deal with this... + // TODO: make .object readonly so we don't have to deal with this... if (self.showsCarousel) { [self refreshScopeTitles]; } @@ -269,7 +269,7 @@ - (void)updateFilteredProperties NSArray *candidateProperties = [self metadata:FLEXMetadataKindProperties forClassAtIndex:self.selectedScope]; NSArray *unsortedFilteredProperties = nil; - if ([self.filterText length] > 0) { + if (self.filterText.length > 0) { NSMutableArray *mutableUnsortedFilteredProperties = [NSMutableArray array]; for (FLEXPropertyBox *propertyBox in candidateProperties) { NSString *prettyName = [FLEXRuntimeUtility prettyNameForProperty:propertyBox.property]; @@ -345,7 +345,7 @@ - (void)updateFilteredIvars NSArray *candidateIvars = [self metadata:FLEXMetadataKindIvars forClassAtIndex:self.selectedScope]; NSArray *unsortedFilteredIvars = nil; - if ([self.filterText length] > 0) { + if (self.filterText.length > 0) { NSMutableArray *mutableUnsortedFilteredIvars = [NSMutableArray array]; for (FLEXIvarBox *ivarBox in candidateIvars) { NSString *prettyName = [FLEXRuntimeUtility prettyNameForIvar:ivarBox.ivar]; @@ -432,7 +432,7 @@ - (void)updateFilteredClassMethods { NSArray *candidateMethods = methods; NSArray *unsortedFilteredMethods = nil; - if ([self.filterText length] > 0) { + if (self.filterText.length > 0) { NSMutableArray *mutableUnsortedFilteredMethods = [NSMutableArray array]; for (FLEXMethodBox *methodBox in candidateMethods) { NSString *prettyName = [FLEXRuntimeUtility prettyNameForMethod:methodBox.method isClassMethod:areClassMethods]; @@ -481,7 +481,7 @@ - (void)updateSuperclasses - (void)updateFilteredSuperclasses { - if ([self.filterText length] > 0) { + if (self.filterText.length > 0) { NSMutableArray *filteredSuperclasses = [NSMutableArray array]; for (Class superclass in self.classHierarchy) { if ([NSStringFromClass(superclass) localizedCaseInsensitiveContainsString:self.filterText]) { @@ -553,32 +553,32 @@ - (NSInteger)numberOfRowsForExplorerSection:(FLEXObjectExplorerSection)section break; case FLEXObjectExplorerSectionCustom: - numberOfRows = [self.customSectionVisibleIndexes count]; + numberOfRows = self.customSectionVisibleIndexes.count; break; case FLEXObjectExplorerSectionProperties: - numberOfRows = [self.filteredProperties count]; + numberOfRows = self.filteredProperties.count; break; case FLEXObjectExplorerSectionIvars: - numberOfRows = [self.filteredIvars count]; + numberOfRows = self.filteredIvars.count; break; case FLEXObjectExplorerSectionMethods: - numberOfRows = [self.filteredMethods count]; + numberOfRows = self.filteredMethods.count; break; case FLEXObjectExplorerSectionClassMethods: - numberOfRows = [self.filteredClassMethods count]; + numberOfRows = self.filteredClassMethods.count; break; case FLEXObjectExplorerSectionSuperclasses: - numberOfRows = [self.filteredSuperclasses count]; + numberOfRows = self.filteredSuperclasses.count; break; case FLEXObjectExplorerSectionReferencingInstances: // Hide this section if there is fliter text since there's nothing searchable (only 1 row, always the same). - numberOfRows = [self.filterText length] == 0 ? 1 : 0; + numberOfRows = self.filterText.length == 0 ? 1 : 0; break; } return numberOfRows; @@ -728,26 +728,26 @@ - (NSString *)titleForExplorerSection:(FLEXObjectExplorerSection)section case FLEXObjectExplorerSectionProperties: { NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindProperties forClassAtIndex:self.selectedScope]; - title = [self sectionTitleWithBaseName:@"Properties" totalCount:totalCount filteredCount:[self.filteredProperties count]]; + title = [self sectionTitleWithBaseName:@"Properties" totalCount:totalCount filteredCount:self.filteredProperties.count]; } break; case FLEXObjectExplorerSectionIvars: { NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindIvars forClassAtIndex:self.selectedScope]; - title = [self sectionTitleWithBaseName:@"Ivars" totalCount:totalCount filteredCount:[self.filteredIvars count]]; + title = [self sectionTitleWithBaseName:@"Ivars" totalCount:totalCount filteredCount:self.filteredIvars.count]; } break; case FLEXObjectExplorerSectionMethods: { NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindMethods forClassAtIndex:self.selectedScope]; - title = [self sectionTitleWithBaseName:@"Methods" totalCount:totalCount filteredCount:[self.filteredMethods count]]; + title = [self sectionTitleWithBaseName:@"Methods" totalCount:totalCount filteredCount:self.filteredMethods.count]; } break; case FLEXObjectExplorerSectionClassMethods: { NSUInteger totalCount = [self totalCountOfMetadata:FLEXMetadataKindClassMethods forClassAtIndex:self.selectedScope]; - title = [self sectionTitleWithBaseName:@"Class Methods" totalCount:totalCount filteredCount:[self.filteredClassMethods count]]; + title = [self sectionTitleWithBaseName:@"Class Methods" totalCount:totalCount filteredCount:self.filteredClassMethods.count]; } break; case FLEXObjectExplorerSectionSuperclasses: { - title = [self sectionTitleWithBaseName:@"Superclasses" totalCount:[self.classHierarchy count] filteredCount:[self.filteredSuperclasses count]]; + title = [self sectionTitleWithBaseName:@"Superclasses" totalCount:self.classHierarchy.count filteredCount:self.filteredSuperclasses.count]; } break; case FLEXObjectExplorerSectionReferencingInstances: { @@ -819,7 +819,7 @@ - (UIViewController *)drillInViewControllerForRow:(NSUInteger)row inExplorerSect - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [[self visibleExplorerSections] count]; + return [self visibleExplorerSections].count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section @@ -851,7 +851,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N UIFont *cellFont = [FLEXUtility defaultTableViewCellLabelFont]; cell.textLabel.font = cellFont; cell.detailTextLabel.font = cellFont; - cell.detailTextLabel.textColor = [UIColor grayColor]; + cell.detailTextLabel.textColor = UIColor.grayColor; } } @@ -963,12 +963,12 @@ - (void)copy:(NSIndexPath *)indexPath stringToCopy = [stringToCopy stringByAppendingString:subtitle]; } - [UIPasteboard generalPasteboard].string = stringToCopy; + UIPasteboard.generalPasteboard.string = stringToCopy; } - (void)copyObjectAddress:(NSIndexPath *)indexPath { - [UIPasteboard generalPasteboard].string = [FLEXUtility addressOfObject:self.object]; + UIPasteboard.generalPasteboard.string = [FLEXUtility addressOfObject:self.object]; } @@ -981,8 +981,8 @@ - (void)updateCustomData - (void)updateFilteredCustomData { - NSIndexSet *filteredIndexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self.cachedCustomSectionRowCookies count])]; - if ([self.filterText length] > 0) { + NSIndexSet *filteredIndexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.cachedCustomSectionRowCookies.count)]; + if (self.filterText.length > 0) { filteredIndexSet = [filteredIndexSet indexesPassingTest:^BOOL(NSUInteger index, BOOL *stop) { BOOL matches = NO; NSString *rowTitle = [self customSectionTitleForRowCookie:self.cachedCustomSectionRowCookies[index]]; diff --git a/Classes/ObjectExplorers/Controllers/FLEXSetExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXSetExplorerViewController.m index f8556d4502..152b93d224 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXSetExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXSetExplorerViewController.m @@ -33,7 +33,7 @@ - (NSString *)customSectionTitle - (NSArray *)customSectionRowCookies { - return [self.set allObjects]; + return self.set.allObjects; } - (NSString *)customSectionTitleForRowCookie:(id)rowCookie diff --git a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m index 5a4ce7b376..2be6af35c6 100644 --- a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m +++ b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m @@ -73,23 +73,23 @@ + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { switch (row) { case FLEXGlobalsRowAppDelegate: { - Class cls = [[UIApplication sharedApplication].delegate class]; + Class cls = [UIApplication.sharedApplication.delegate class]; return [NSString stringWithFormat:@"👉 %@", cls]; } case FLEXGlobalsRowProcessInfo: - return @"🚦 +[NSProcessInfo processInfo]"; + return @"🚦 +NSProcessInfo.processInfo"; case FLEXGlobalsRowUserDefaults: return @"💾 +[NSUserDefaults standardUserDefaults]"; case FLEXGlobalsRowMainBundle: return @"📦 +[NSBundle mainBundle]"; case FLEXGlobalsRowApplication: - return @"🚀 +[UIApplication sharedApplication]"; + return @"🚀 +UIApplication.sharedApplication"; case FLEXGlobalsRowMainScreen: - return @"💻 +[UIScreen mainScreen]"; + return @"💻 +UIScreen.mainScreen"; case FLEXGlobalsRowCurrentDevice: return @"📱 +[UIDevice currentDevice]"; case FLEXGlobalsRowPasteboard: - return @"📋 +[UIPasteboard generalPastboard]"; + return @"📋 +UIPasteboard.generalPastboard"; default: return nil; } } @@ -98,23 +98,23 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { switch (row) { case FLEXGlobalsRowAppDelegate: { - id appDelegate = [UIApplication sharedApplication].delegate; + id appDelegate = UIApplication.sharedApplication.delegate; return [self explorerViewControllerForObject:appDelegate]; } case FLEXGlobalsRowProcessInfo: - return [self explorerViewControllerForObject:[NSProcessInfo processInfo]];; + return [self explorerViewControllerForObject:NSProcessInfo.processInfo];; case FLEXGlobalsRowUserDefaults: return [self explorerViewControllerForObject:[NSUserDefaults standardUserDefaults]]; case FLEXGlobalsRowMainBundle: return [self explorerViewControllerForObject:[NSBundle mainBundle]]; case FLEXGlobalsRowApplication: - return [self explorerViewControllerForObject:[UIApplication sharedApplication]]; + return [self explorerViewControllerForObject:UIApplication.sharedApplication]; case FLEXGlobalsRowMainScreen: - return [self explorerViewControllerForObject:[UIScreen mainScreen]]; + return [self explorerViewControllerForObject:UIScreen.mainScreen]; case FLEXGlobalsRowCurrentDevice: return [self explorerViewControllerForObject:[UIDevice currentDevice]]; case FLEXGlobalsRowPasteboard: - return [self explorerViewControllerForObject:[UIPasteboard generalPasteboard]]; + return [self explorerViewControllerForObject:UIPasteboard.generalPasteboard]; default: return nil; } } diff --git a/Classes/ObjectExplorers/Views/FLEXTableViewCell.m b/Classes/ObjectExplorers/Views/FLEXTableViewCell.m index 296ba36e84..383d3e91a7 100644 --- a/Classes/ObjectExplorers/Views/FLEXTableViewCell.m +++ b/Classes/ObjectExplorers/Views/FLEXTableViewCell.m @@ -30,7 +30,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus UIFont *cellFont = [FLEXUtility defaultTableViewCellLabelFont]; self.textLabel.font = cellFont; self.detailTextLabel.font = cellFont; - self.detailTextLabel.textColor = [UIColor grayColor]; + self.detailTextLabel.textColor = UIColor.grayColor; } return self; diff --git a/Classes/Toolbar/FLEXExplorerToolbar.m b/Classes/Toolbar/FLEXExplorerToolbar.m index be98f76d59..b7876e66c7 100644 --- a/Classes/Toolbar/FLEXExplorerToolbar.m +++ b/Classes/Toolbar/FLEXExplorerToolbar.m @@ -43,7 +43,7 @@ - (id)initWithFrame:(CGRect)frame [self addSubview:self.backgroundView]; self.dragHandle = [[UIView alloc] init]; - self.dragHandle.backgroundColor = [UIColor clearColor]; + self.dragHandle.backgroundColor = UIColor.clearColor; [self addSubview:self.dragHandle]; UIImage *dragHandle = [FLEXResources dragHandle]; @@ -72,15 +72,15 @@ - (id)initWithFrame:(CGRect)frame [self addSubview:self.selectedViewDescriptionContainer]; self.selectedViewDescriptionSafeAreaContainer = [[UIView alloc] init]; - self.selectedViewDescriptionSafeAreaContainer.backgroundColor = [UIColor clearColor]; + self.selectedViewDescriptionSafeAreaContainer.backgroundColor = UIColor.clearColor; [self.selectedViewDescriptionContainer addSubview:self.selectedViewDescriptionSafeAreaContainer]; self.selectedViewColorIndicator = [[UIView alloc] init]; - self.selectedViewColorIndicator.backgroundColor = [UIColor redColor]; + self.selectedViewColorIndicator.backgroundColor = UIColor.redColor; [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewColorIndicator]; self.selectedViewDescriptionLabel = [[UILabel alloc] init]; - self.selectedViewDescriptionLabel.backgroundColor = [UIColor clearColor]; + self.selectedViewDescriptionLabel.backgroundColor = UIColor.clearColor; self.selectedViewDescriptionLabel.font = [[self class] descriptionLabelFont]; [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewDescriptionLabel]; @@ -109,14 +109,14 @@ - (void)layoutSubviews CGFloat originX = CGRectGetMaxX(self.dragHandle.frame); CGFloat originY = CGRectGetMinY(safeArea); CGFloat height = kToolbarItemHeight; - CGFloat width = FLEXFloor((CGRectGetWidth(safeArea) - CGRectGetWidth(self.dragHandle.frame)) / [self.toolbarItems count]); + CGFloat width = FLEXFloor((CGRectGetWidth(safeArea) - CGRectGetWidth(self.dragHandle.frame)) / self.toolbarItems.count); for (UIView *toolbarItem in self.toolbarItems) { toolbarItem.frame = CGRectMake(originX, originY, width, height); originX = CGRectGetMaxX(toolbarItem.frame); } // Make sure the last toolbar item goes to the edge to account for any accumulated rounding effects. - UIView *lastToolbarItem = [self.toolbarItems lastObject]; + UIView *lastToolbarItem = self.toolbarItems.lastObject; CGRect lastToolbarItemFrame = lastToolbarItem.frame; lastToolbarItemFrame.size.width = CGRectGetMaxX(safeArea) - lastToolbarItemFrame.origin.x; lastToolbarItem.frame = lastToolbarItemFrame; @@ -204,7 +204,7 @@ - (void)setSelectedViewDescription:(NSString *)selectedViewDescription if (![_selectedViewDescription isEqual:selectedViewDescription]) { _selectedViewDescription = selectedViewDescription; self.selectedViewDescriptionLabel.text = selectedViewDescription; - BOOL showDescription = [selectedViewDescription length] > 0; + BOOL showDescription = selectedViewDescription.length > 0; self.selectedViewDescriptionContainer.hidden = !showDescription; } } diff --git a/Classes/Toolbar/FLEXToolbarItem.m b/Classes/Toolbar/FLEXToolbarItem.m index 86940f1798..40af50682e 100644 --- a/Classes/Toolbar/FLEXToolbarItem.m +++ b/Classes/Toolbar/FLEXToolbarItem.m @@ -54,7 +54,7 @@ + (UIColor *)selectedBackgroundColor + (UIColor *)defaultBackgroundColor { - return [UIColor clearColor]; + return UIColor.clearColor; } + (CGFloat)topMargin diff --git a/Classes/Utility/FLEXColor.m b/Classes/Utility/FLEXColor.m index 4df069e8c7..fa97f4a503 100644 --- a/Classes/Utility/FLEXColor.m +++ b/Classes/Utility/FLEXColor.m @@ -72,12 +72,12 @@ + (UIColor *)deemphasizedTextColor { + (UIColor *)tintColor { #if FLEX_AT_LEAST_IOS13_SDK if (@available(iOS 13.0, *)) { - return [UIColor systemBlueColor]; + return UIColor.systemBlueColor; } else { - return [UIApplication sharedApplication].keyWindow.tintColor; + return UIApplication.sharedApplication.keyWindow.tintColor; } #else - return [UIApplication sharedApplication].keyWindow.tintColor; + return UIApplication.sharedApplication.keyWindow.tintColor; #endif } diff --git a/Classes/Utility/FLEXKeyboardHelpViewController.m b/Classes/Utility/FLEXKeyboardHelpViewController.m index e0e8c1a853..1dd5a91f7c 100644 --- a/Classes/Utility/FLEXKeyboardHelpViewController.m +++ b/Classes/Utility/FLEXKeyboardHelpViewController.m @@ -27,8 +27,8 @@ - (void)viewDidLoad #if TARGET_OS_SIMULATOR self.textView.text = [[FLEXKeyboardShortcutManager sharedManager] keyboardShortcutsDescription]; #endif - self.textView.backgroundColor = [UIColor blackColor]; - self.textView.textColor = [UIColor whiteColor]; + self.textView.backgroundColor = UIColor.blackColor; + self.textView.textColor = UIColor.whiteColor; self.textView.font = [UIFont boldSystemFontOfSize:14.0]; self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.m b/Classes/Utility/FLEXKeyboardShortcutManager.m index 33a46b512a..101dd86f5e 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.m +++ b/Classes/Utility/FLEXKeyboardShortcutManager.m @@ -86,7 +86,7 @@ - (NSString *)description } // Fudging to get easy columns with tabs - if ([prettyFlags length] < 2) { + if (prettyFlags.length < 2) { prettyKey = [prettyKey stringByAppendingString:@"\t"]; } @@ -239,9 +239,9 @@ - (void)handleKeyboardEvent:(UIEvent *)event isKeyDown = [event _isKeyDown]; } - BOOL interactionEnabled = ![[UIApplication sharedApplication] isIgnoringInteractionEvents]; + BOOL interactionEnabled = ![UIApplication.sharedApplication isIgnoringInteractionEvents]; BOOL hasFirstResponder = NO; - if (isKeyDown && [modifiedInput length] > 0 && interactionEnabled) { + if (isKeyDown && modifiedInput.length > 0 && interactionEnabled) { UIResponder *firstResponder = nil; for (UIWindow *window in [FLEXUtility allWindows]) { firstResponder = [window valueForKey:@"firstResponder"]; @@ -294,7 +294,7 @@ - (void)handleKeyboardEvent:(UIEvent *)event - (NSString *)keyboardShortcutsDescription { NSMutableString *description = [NSMutableString string]; - NSArray *keyInputs = [[self.actionsForKeyInputs allKeys] sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *_Nonnull input1, FLEXKeyInput *_Nonnull input2) { + NSArray *keyInputs = [self.actionsForKeyInputs.allKeys sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *_Nonnull input1, FLEXKeyInput *_Nonnull input2) { return [input1.key caseInsensitiveCompare:input2.key]; }]; for (FLEXKeyInput *keyInput in keyInputs) { diff --git a/Classes/Utility/FLEXResources.m b/Classes/Utility/FLEXResources.m index d821bf9401..5cc14bfff4 100644 --- a/Classes/Utility/FLEXResources.m +++ b/Classes/Utility/FLEXResources.m @@ -83,7 +83,7 @@ @implementation FLEXResources #pragma mark - Images -#define FLEXImage(base) (([[UIScreen mainScreen] scale] > 1.5) ? \ +#define FLEXImage(base) ((UIScreen.mainScreen.scale > 1.5) ? \ [self imageWithBytesNoCopy:(void *)base##2x length:sizeof(base##2x) scale:2.0] : \ [self imageWithBytesNoCopy:(void *)base length:sizeof(base) scale:1.0]) diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 83007c98be..f3c6ce0061 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -190,7 +190,7 @@ + (id)valueForProperty:(objc_property_t)property onObject:(id)object } SEL getterSelector; - if ([customGetterString length] > 0) { + if (customGetterString.length > 0) { getterSelector = NSSelectorFromString(customGetterString); } else { NSString *propertyName = @(property_getName(property)); @@ -239,14 +239,14 @@ + (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary *components = [self prettyArgumentComponentsForMethod:method]; - if ([components count] > 0) { + if (components.count > 0) { prettyName = [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]]; } else { prettyName = [prettyName stringByAppendingString:selectorName]; @@ -396,7 +396,7 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * NSUInteger numberOfArguments = [methodSignature numberOfArguments]; for (NSUInteger argumentIndex = kFLEXNumberOfImplicitArgs; argumentIndex < numberOfArguments; argumentIndex++) { NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs; - id argumentObject = [arguments count] > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil; + id argumentObject = arguments.count > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil; // NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil. if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) { @@ -446,7 +446,7 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * [invocation invoke]; // Retrieve the return value and box if necessary. - const char *returnType = [methodSignature methodReturnType]; + const char *returnType = methodSignature.methodReturnType; if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) { // Return value is an object. @@ -455,7 +455,7 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * returnObject = objectReturnedFromMethod; } else if (returnType[0] != @encode(void)[0]) { // Will use arbitrary buffer for return value and box it. - void *returnValue = malloc([methodSignature methodReturnLength]); + void *returnValue = malloc(methodSignature.methodReturnLength); if (returnValue) { [invocation getReturnValue:returnValue]; @@ -534,7 +534,7 @@ + (NSString *)editableJSONStringForObject:(id)object NSArray *wrappedObject = @[object]; if ([NSJSONSerialization isValidJSONObject:wrappedObject]) { NSString *wrappedDescription = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL] encoding:NSUTF8StringEncoding]; - editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, [wrappedDescription length] - 2)]; + editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, wrappedDescription.length - 2)]; } } @@ -624,7 +624,7 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here. const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL); NSString *typeEncoding = [@(structEncoding) substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)]; - typeBlock(structName, [typeEncoding UTF8String], [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset); + typeBlock(structName, typeEncoding.UTF8String, [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset); runningFieldOffset += fieldSize; // Padding to keep proper alignment. __attribute((packed)) structs will break here. // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those. @@ -647,7 +647,7 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( NSString *attributes = @(property_getAttributes(property)); // Thanks to MAObjcRuntime for inspiration here. NSArray *attributePairs = [attributes componentsSeparatedByString:@","]; - NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionaryWithCapacity:[attributePairs count]]; + NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionaryWithCapacity:attributePairs.count]; for (NSString *attributePair in attributePairs) { [attributesDictionary setObject:[attributePair substringFromIndex:1] forKey:[attributePair substringToIndex:1]]; } @@ -657,7 +657,7 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( + (NSString *)appendName:(NSString *)name toType:(NSString *)type { NSString *combined = nil; - if ([type characterAtIndex:[type length] - 1] == '*') { + if ([type characterAtIndex:type.length - 1] == '*') { combined = [type stringByAppendingString:name]; } else { combined = [type stringByAppendingFormat:@" %@", name]; @@ -676,13 +676,13 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString // See https://github.com/nygard/class-dump/blob/master/Source/CDType.m // Warning: this method uses multiple middle returns and macros to cut down on boilerplate. // The use of macros here was inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html - const char *encodingCString = [encodingString UTF8String]; + const char *encodingCString = encodingString.UTF8String; // Objects if (encodingCString[0] == '@') { NSString *class = [encodingString substringFromIndex:1]; class = [class stringByReplacingOccurrencesOfString:@"\"" withString:@""]; - if ([class length] == 0 || [class isEqual:@"?"]) { + if (class.length == 0 || [class isEqual:@"?"]) { class = @"id"; } else { class = [class stringByAppendingString:@" *"]; diff --git a/Classes/Utility/FLEXUtility.h b/Classes/Utility/FLEXUtility.h index c3f76ec562..c8035ff92c 100644 --- a/Classes/Utility/FLEXUtility.h +++ b/Classes/Utility/FLEXUtility.h @@ -12,7 +12,7 @@ #import #import -#define FLEXFloor(x) (floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale]) +#define FLEXFloor(x) (floor(UIScreen.mainScreen.scale * (x)) / UIScreen.mainScreen.scale) #if defined(__IPHONE_13_0) #define FLEX_AT_LEAST_IOS13_SDK (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index cf9c39ad98..c1773c8d95 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -26,7 +26,7 @@ + (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFram NSString *description = [[view class] description]; NSString *viewControllerDescription = [[[self viewControllerForView:view] class] description]; - if ([viewControllerDescription length] > 0) { + if (viewControllerDescription.length > 0) { description = [description stringByAppendingFormat:@" (%@)", viewControllerDescription]; } @@ -34,7 +34,7 @@ + (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFram description = [description stringByAppendingFormat:@" %@", [self stringForCGRect:view.frame]]; } - if ([view.accessibilityLabel length] > 0) { + if (view.accessibilityLabel.length > 0) { description = [description stringByAppendingFormat:@" · %@", view.accessibilityLabel]; } @@ -82,7 +82,7 @@ + (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius CGFloat diameter = radius * 2.0; UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), NO, 0.0); CGContextRef imageContext = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(imageContext, [color CGColor]); + CGContextSetFillColorWithColor(imageContext, color.CGColor); CGContextFillEllipseInRect(imageContext, CGRectMake(0, 0, diameter, diameter)); UIImage *circularImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); @@ -192,7 +192,7 @@ + (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString NSMutableString *mutableString = [originalString mutableCopy]; - NSArray *matches = [regex matchesInString:mutableString options:0 range:NSMakeRange(0, [mutableString length])]; + NSArray *matches = [regex matchesInString:mutableString options:0 range:NSMakeRange(0, mutableString.length)]; for (NSTextCheckingResult *result in [matches reverseObjectEnumerator]) { NSString *foundString = [mutableString substringWithRange:result.range]; NSString *replacementString = escapingDictionary[foundString]; @@ -295,9 +295,9 @@ + (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response for (NSString *keyValueString in queryComponents) { // [a, 1] NSArray *components = [keyValueString componentsSeparatedByString:@"="]; - if ([components count] == 2) { - NSString *key = [[components firstObject] stringByRemovingPercentEncoding]; - id value = [[components lastObject] stringByRemovingPercentEncoding]; + if (components.count == 2) { + NSString *key = [components.firstObject stringByRemovingPercentEncoding]; + id value = [components.lastObject stringByRemovingPercentEncoding]; // Handle multiple entries under the same key as an array id existingEntry = queryDictionary[key]; @@ -343,13 +343,13 @@ + (BOOL)isValidJSONData:(NSData *)data + (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData { NSData *inflatedData = nil; - NSUInteger compressedDataLength = [compressedData length]; + NSUInteger compressedDataLength = compressedData.length; if (compressedDataLength > 0) { z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.avail_in = (uInt)compressedDataLength; - stream.next_in = (void *)[compressedData bytes]; + stream.next_in = (void *)compressedData.bytes; stream.total_out = 0; stream.avail_out = 0; @@ -357,11 +357,11 @@ + (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData if (inflateInit2(&stream, 15 + 32) == Z_OK) { int status = Z_OK; while (status == Z_OK) { - if (stream.total_out >= [mutableData length]) { + if (stream.total_out >= mutableData.length) { mutableData.length += compressedDataLength / 2; } stream.next_out = (uint8_t *)[mutableData mutableBytes] + stream.total_out; - stream.avail_out = (uInt)([mutableData length] - stream.total_out); + stream.avail_out = (uInt)(mutableData.length - stream.total_out); status = inflate(&stream, Z_SYNC_FLUSH); } if (inflateEnd(&stream) == Z_OK) { diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m index a8d64dd9bc..9befa6c1d3 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m @@ -31,7 +31,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus self.depthIndicatorView.backgroundColor = [FLEXUtility hierarchyIndentPatternColor]; [self.contentView addSubview:self.depthIndicatorView]; - UIImage *defaultCircleImage = [FLEXUtility circularImageWithColor:[UIColor blackColor] radius:5.0]; + UIImage *defaultCircleImage = [FLEXUtility circularImageWithColor:UIColor.blackColor radius:5.0]; self.colorCircleImageView = [[UIImageView alloc] initWithImage:defaultCircleImage]; [self.contentView addSubview:self.colorCircleImageView]; @@ -41,7 +41,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus self.viewBackgroundColorView = [[UIView alloc] init]; self.viewBackgroundColorView.clipsToBounds = YES; - self.viewBackgroundColorView.layer.borderColor = [UIColor blackColor].CGColor; + self.viewBackgroundColorView.layer.borderColor = UIColor.blackColor.CGColor; self.viewBackgroundColorView.layer.borderWidth = 1.0f; [self.contentView addSubview:self.viewBackgroundColorView]; } diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m b/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m index a712a87ab0..94e9e18042 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m @@ -121,7 +121,7 @@ - (void)updateDisplayedViews - (BOOL)showScopeBar { - return [self.viewsAtTap count] > 0; + return self.viewsAtTap.count > 0; } - (void)updateSearchResults:(NSString *)newText @@ -143,7 +143,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.displayedViews count]; + return self.displayedViews.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -177,7 +177,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N }); UIColor *viewColour = view.backgroundColor; - if (!viewColour || [viewColour isEqual:[UIColor clearColor]]) { + if (!viewColour || [viewColour isEqual:UIColor.clearColor]) { cell.viewBackgroundColorView.backgroundColor = checkerPatternColour; } else { cell.viewBackgroundColorView.backgroundColor = viewColour; diff --git a/Example/UICatalog.xcodeproj/project.pbxproj b/Example/UICatalog.xcodeproj/project.pbxproj index ded1bdaaec..5441d4c41b 100644 --- a/Example/UICatalog.xcodeproj/project.pbxproj +++ b/Example/UICatalog.xcodeproj/project.pbxproj @@ -366,6 +366,7 @@ ORGANIZATIONNAME = f; TargetAttributes = { 5356823918F3656900BAAD62 = { + DevelopmentTeam = S6N2F22V2Z; ProvisioningStyle = Automatic; }; }; @@ -584,7 +585,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = S6N2F22V2Z; EXCLUDED_SOURCE_FILE_NAMES = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -607,7 +608,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = S6N2F22V2Z; EXCLUDED_SOURCE_FILE_NAMES = "FLEX*"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/Example/UICatalog/AAPLActivityIndicatorViewController.m b/Example/UICatalog/AAPLActivityIndicatorViewController.m index 59352c38e8..23e75489ff 100644 --- a/Example/UICatalog/AAPLActivityIndicatorViewController.m +++ b/Example/UICatalog/AAPLActivityIndicatorViewController.m @@ -82,7 +82,7 @@ - (void)configureGrayActivityIndicatorView { - (void)configureTintedActivityIndicatorView { self.tintedActivityIndicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; - self.tintedActivityIndicatorView.color = [UIColor aapl_applicationPurpleColor]; + self.tintedActivityIndicatorView.color = UIColor.aapl_applicationPurpleColor; [self.tintedActivityIndicatorView startAnimating]; } diff --git a/Example/UICatalog/AAPLAppDelegate.m b/Example/UICatalog/AAPLAppDelegate.m index 250078ed1f..518bbd9c56 100644 --- a/Example/UICatalog/AAPLAppDelegate.m +++ b/Example/UICatalog/AAPLAppDelegate.m @@ -112,7 +112,7 @@ - (void)sendExampleNetworkRequests }); // NSURLSession - NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSessionConfiguration *config = NSURLSessionConfiguration.defaultSessionConfiguration; config.timeoutIntervalForRequest = 10.0; NSURLSession *mySession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; @@ -125,12 +125,12 @@ - (void)sendExampleNetworkRequests [pendingTasks addObject:[mySession downloadTaskWithURL:[NSURL URLWithString:@"https://assets-cdn.github.com/images/icons/emoji/unicode/1f44d.png?v5"]]]; // Async NSURLSessionDownloadTask - [pendingTasks addObject:[[NSURLSession sharedSession] downloadTaskWithURL:[NSURL URLWithString:@"http://lorempixel.com/1024/1024/"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { + [pendingTasks addObject:[NSURLSession.sharedSession downloadTaskWithURL:[NSURL URLWithString:@"http://lorempixel.com/1024/1024/"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { }]]; // Async NSURLSessionDataTask - [pendingTasks addObject:[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://api.github.com/emojis"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + [pendingTasks addObject:[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:@"https://api.github.com/emojis"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }]]; @@ -193,9 +193,9 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err #if __has_include() - (void)setUpRealm { - NSString *destinationPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; + NSString *destinationPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; destinationPath = [destinationPath stringByAppendingPathComponent:@"dogs.realm"]; - if ([[NSFileManager defaultManager] fileExistsAtPath:destinationPath isDirectory:nil]) { + if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath isDirectory:nil]) { return; } @@ -205,7 +205,7 @@ - (void)setUpRealm } NSError *error = nil; - [[NSFileManager defaultManager] copyItemAtPath:resourcePath toPath:destinationPath error:&error]; + [NSFileManager.defaultManager copyItemAtPath:resourcePath toPath:destinationPath error:&error]; } #endif diff --git a/Example/UICatalog/AAPLButtonViewController.m b/Example/UICatalog/AAPLButtonViewController.m index 6ee9fb40dd..8ddb175abe 100644 --- a/Example/UICatalog/AAPLButtonViewController.m +++ b/Example/UICatalog/AAPLButtonViewController.m @@ -83,13 +83,13 @@ - (void)configureSystemTextButton { } - (void)configureSystemContactAddButton { - self.systemContactAddButton.backgroundColor = [UIColor clearColor]; + self.systemContactAddButton.backgroundColor = UIColor.clearColor; [self.systemContactAddButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; } - (void)configureSystemDetailDisclosureButton { - self.systemDetailDisclosureButton.backgroundColor = [UIColor clearColor]; + self.systemDetailDisclosureButton.backgroundColor = UIColor.clearColor; [self.systemDetailDisclosureButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; } @@ -100,7 +100,7 @@ - (void)configureImageButton { // Remove the title text. [self.imageButton setTitle:@"" forState:UIControlStateNormal]; - self.imageButton.tintColor = [UIColor aapl_applicationPurpleColor]; + self.imageButton.tintColor = UIColor.aapl_applicationPurpleColor; [self.imageButton setImage:[UIImage imageNamed:@"x_icon"] forState:UIControlStateNormal]; @@ -111,11 +111,11 @@ - (void)configureImageButton { } - (void)configureAttributedTextSystemButton { - NSDictionary *titleAttributes = @{NSForegroundColorAttributeName: [UIColor aapl_applicationBlueColor], NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle)}; + NSDictionary *titleAttributes = @{NSForegroundColorAttributeName: UIColor.aapl_applicationBlueColor, NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle)}; NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:NSLocalizedString(@"Button", nil) attributes:titleAttributes]; [self.attributedTextButton setAttributedTitle:attributedTitle forState:UIControlStateNormal]; - NSDictionary *highlightedTitleAttributes = @{NSForegroundColorAttributeName : [UIColor aapl_applicationGreenColor], NSStrikethroughStyleAttributeName: @(NSUnderlineStyleThick)}; + NSDictionary *highlightedTitleAttributes = @{NSForegroundColorAttributeName : UIColor.aapl_applicationGreenColor, NSStrikethroughStyleAttributeName: @(NSUnderlineStyleThick)}; NSAttributedString *highlightedAttributedTitle = [[NSAttributedString alloc] initWithString:NSLocalizedString(@"Button", nil) attributes:highlightedTitleAttributes]; [self.attributedTextButton setAttributedTitle:highlightedAttributedTitle forState:UIControlStateHighlighted]; diff --git a/Example/UICatalog/AAPLCatalogTableTableViewController.m b/Example/UICatalog/AAPLCatalogTableTableViewController.m index 300e2d1b7c..1fc8487927 100644 --- a/Example/UICatalog/AAPLCatalogTableTableViewController.m +++ b/Example/UICatalog/AAPLCatalogTableTableViewController.m @@ -44,7 +44,7 @@ - (void)registerViewControllerBasedOption infoLabel.textAlignment = NSTextAlignmentCenter; UIView *view = viewController.view; - view.backgroundColor = [UIColor whiteColor]; + view.backgroundColor = UIColor.whiteColor; [view addSubview:infoLabel]; [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[infoLabel]-0-|" diff --git a/Example/UICatalog/AAPLCustomSearchBarViewController.m b/Example/UICatalog/AAPLCustomSearchBarViewController.m index a4a1094f5b..c9d16d0625 100644 --- a/Example/UICatalog/AAPLCustomSearchBarViewController.m +++ b/Example/UICatalog/AAPLCustomSearchBarViewController.m @@ -71,7 +71,7 @@ - (void)configureSearchBar { self.searchBar.showsCancelButton = YES; self.searchBar.showsBookmarkButton = YES; - self.searchBar.tintColor = [UIColor aapl_applicationPurpleColor]; + self.searchBar.tintColor = UIColor.aapl_applicationPurpleColor; self.searchBar.backgroundImage = [UIImage imageNamed:@"search_bar_background"]; diff --git a/Example/UICatalog/AAPLCustomToolbarViewController.m b/Example/UICatalog/AAPLCustomToolbarViewController.m index a241140069..cd1977de98 100644 --- a/Example/UICatalog/AAPLCustomToolbarViewController.m +++ b/Example/UICatalog/AAPLCustomToolbarViewController.m @@ -81,7 +81,7 @@ - (void)configureToolbar { - (UIBarButtonItem *)customImageBarButtonItem { UIBarButtonItem *customImageBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"tools_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(barButtonItemClicked:)]; - customImageBarButtonItem.tintColor = [UIColor aapl_applicationPurpleColor]; + customImageBarButtonItem.tintColor = UIColor.aapl_applicationPurpleColor; return customImageBarButtonItem; } @@ -93,7 +93,7 @@ - (UIBarButtonItem *)flexibleSpaceBarButtonItem { - (UIBarButtonItem *)customBarButtonItem { UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Button", nil) style:UIBarButtonItemStylePlain target:self action:@selector(barButtonItemClicked:)]; - NSDictionary *attributes = @{NSForegroundColorAttributeName: [UIColor aapl_applicationPurpleColor]}; + NSDictionary *attributes = @{NSForegroundColorAttributeName: UIColor.aapl_applicationPurpleColor}; [barButtonItem setTitleTextAttributes:attributes forState:UIControlStateNormal]; return barButtonItem; diff --git a/Example/UICatalog/AAPLImageViewController.m b/Example/UICatalog/AAPLImageViewController.m index 36d517ee90..f8122cfd21 100644 --- a/Example/UICatalog/AAPLImageViewController.m +++ b/Example/UICatalog/AAPLImageViewController.m @@ -67,7 +67,7 @@ - (void)viewDidLoad { imageView.contentMode = UIViewContentModeScaleAspectFit; // If the image does not have the same aspect ratio as imageView's bounds, then imageView's backgroundColor will be applied to the "empty" space. - imageView.backgroundColor = [UIColor whiteColor]; + imageView.backgroundColor = UIColor.whiteColor; imageView.animationDuration = 5; [imageView startAnimating]; diff --git a/Example/UICatalog/AAPLMasterViewController.m b/Example/UICatalog/AAPLMasterViewController.m index 1b2e858a00..8aa16ba040 100644 --- a/Example/UICatalog/AAPLMasterViewController.m +++ b/Example/UICatalog/AAPLMasterViewController.m @@ -79,7 +79,7 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) { #pragma clang diagnostic pop UINavigationController *newDetailViewController = [segue destinationViewController]; - UINavigationController *oldDetailViewController = [self.splitViewController.viewControllers lastObject]; + UINavigationController *oldDetailViewController = self.splitViewController.viewControllers.lastObject; // In order for a segue to occur when the view controller is in portrait, the "More" bar button item must be visible. // However, the "More" bar button item is only visible if the detail view controller's root view controller is diff --git a/Example/UICatalog/AAPLPageControlViewController.m b/Example/UICatalog/AAPLPageControlViewController.m index 3cc6b827b8..6f67df6e98 100644 --- a/Example/UICatalog/AAPLPageControlViewController.m +++ b/Example/UICatalog/AAPLPageControlViewController.m @@ -65,7 +65,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // Set a list of colors that correspond to the selected page. - self.colors = @[[UIColor blackColor], [UIColor grayColor], [UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor cyanColor], [UIColor yellowColor], [UIColor magentaColor], [UIColor orangeColor], [UIColor purpleColor]]; + self.colors = @[UIColor.blackColor, UIColor.grayColor, UIColor.redColor, UIColor.greenColor, UIColor.blueColor, UIColor.cyanColor, UIColor.yellowColor, UIColor.magentaColor, UIColor.orangeColor, UIColor.purpleColor]; [self configurePageControl]; [self pageControlValueDidChange]; @@ -76,12 +76,12 @@ - (void)viewDidLoad { - (void)configurePageControl { // The total number of pages that are available is based on how many available colors we have. - self.pageControl.numberOfPages = [self.colors count]; + self.pageControl.numberOfPages = self.colors.count; self.pageControl.currentPage = 2; - self.pageControl.tintColor = [UIColor aapl_applicationBlueColor]; - self.pageControl.pageIndicatorTintColor = [UIColor aapl_applicationGreenColor]; - self.pageControl.currentPageIndicatorTintColor = [UIColor aapl_applicationPurpleColor]; + self.pageControl.tintColor = UIColor.aapl_applicationBlueColor; + self.pageControl.pageIndicatorTintColor = UIColor.aapl_applicationGreenColor; + self.pageControl.currentPageIndicatorTintColor = UIColor.aapl_applicationPurpleColor; [self.pageControl addTarget:self action:@selector(pageControlValueDidChange) forControlEvents:UIControlEventValueChanged]; } diff --git a/Example/UICatalog/AAPLProgressViewController.m b/Example/UICatalog/AAPLProgressViewController.m index 295afb7a3f..de948f8673 100644 --- a/Example/UICatalog/AAPLProgressViewController.m +++ b/Example/UICatalog/AAPLProgressViewController.m @@ -109,8 +109,8 @@ - (void)configureBarStyleProgressView { - (void)configureTintedProgressView { self.tintedProgressView.progressViewStyle = UIProgressViewStyleDefault; - self.tintedProgressView.trackTintColor = [UIColor aapl_applicationBlueColor]; - self.tintedProgressView.progressTintColor = [UIColor aapl_applicationPurpleColor]; + self.tintedProgressView.trackTintColor = UIColor.aapl_applicationBlueColor; + self.tintedProgressView.progressTintColor = UIColor.aapl_applicationPurpleColor; } diff --git a/Example/UICatalog/AAPLSegmentedControlViewController.m b/Example/UICatalog/AAPLSegmentedControlViewController.m index 36ff15f28d..7a5df5a71b 100644 --- a/Example/UICatalog/AAPLSegmentedControlViewController.m +++ b/Example/UICatalog/AAPLSegmentedControlViewController.m @@ -82,7 +82,7 @@ - (void)configureDefaultSegmentedControl { } - (void)configureTintedSegmentedControl { - self.tintedSegmentedControl.tintColor = [UIColor aapl_applicationBlueColor]; + self.tintedSegmentedControl.tintColor = UIColor.aapl_applicationBlueColor; self.tintedSegmentedControl.selectedSegmentIndex = 1; @@ -97,7 +97,7 @@ - (void)configureCustomSegmentsSegmentedControl { }; // Guarantee that the segments show up in the same order. - NSArray *sortedSegmentImageNames = [[imageToAccessibilityLabelMappings allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + NSArray *sortedSegmentImageNames = [imageToAccessibilityLabelMappings.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; [sortedSegmentImageNames enumerateObjectsUsingBlock:^(NSString *segmentImageName, NSUInteger idx, BOOL *stop) { UIImage *image = [UIImage imageNamed:segmentImageName]; @@ -126,10 +126,10 @@ - (void)configureCustomBackgroundSegmentedControl { UIFontDescriptor *captionFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1]; UIFont *font = [UIFont fontWithDescriptor:captionFontDescriptor size:0]; - NSDictionary *normalTextAttributes = @{NSForegroundColorAttributeName:[UIColor aapl_applicationPurpleColor], NSFontAttributeName:font}; + NSDictionary *normalTextAttributes = @{NSForegroundColorAttributeName:UIColor.aapl_applicationPurpleColor, NSFontAttributeName:font}; [self.customBackgroundSegmentedControl setTitleTextAttributes:normalTextAttributes forState:UIControlStateNormal]; - NSDictionary *highlightedTextAttributes = @{NSForegroundColorAttributeName:[UIColor aapl_applicationGreenColor], NSFontAttributeName:font}; + NSDictionary *highlightedTextAttributes = @{NSForegroundColorAttributeName:UIColor.aapl_applicationGreenColor, NSFontAttributeName:font}; [self.customBackgroundSegmentedControl setTitleTextAttributes:highlightedTextAttributes forState:UIControlStateHighlighted]; [self.customBackgroundSegmentedControl addTarget:self action:@selector(selectedSegmentDidChange:) forControlEvents:UIControlEventValueChanged]; diff --git a/Example/UICatalog/AAPLSliderViewController.m b/Example/UICatalog/AAPLSliderViewController.m index 1aaaf985af..f7af0e248a 100644 --- a/Example/UICatalog/AAPLSliderViewController.m +++ b/Example/UICatalog/AAPLSliderViewController.m @@ -81,8 +81,8 @@ - (void)configureDefaultSlider { } - (void)configureTintedSlider { - self.tintedSlider.minimumTrackTintColor = [UIColor aapl_applicationBlueColor]; - self.tintedSlider.maximumTrackTintColor = [UIColor aapl_applicationPurpleColor]; + self.tintedSlider.minimumTrackTintColor = UIColor.aapl_applicationBlueColor; + self.tintedSlider.maximumTrackTintColor = UIColor.aapl_applicationPurpleColor; [self.tintedSlider addTarget:self action:@selector(sliderValueDidChange:) forControlEvents:UIControlEventValueChanged]; } diff --git a/Example/UICatalog/AAPLSplitViewControllerDelegate.m b/Example/UICatalog/AAPLSplitViewControllerDelegate.m index 830076cc1c..97fcab63b4 100644 --- a/Example/UICatalog/AAPLSplitViewControllerDelegate.m +++ b/Example/UICatalog/AAPLSplitViewControllerDelegate.m @@ -58,12 +58,12 @@ @implementation AAPLSplitViewControllerDelegate - (void)splitViewController:(UISplitViewController *)splitViewController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController { barButtonItem.title = NSLocalizedString(@"UICatalog", nil); - UINavigationController *detailViewController = [splitViewController.viewControllers lastObject]; + UINavigationController *detailViewController = splitViewController.viewControllers.lastObject; // It's possible that the detail view controller has more than one view controller currently in its hierarchy. If this is the case, we // want to be sure that the root view controller of the navigation controller has its left bar button item set on its navigation item. // We don't want to override the navigation controller's top view controller's "Back" bar button item with the "More" bar button item. - UIViewController *detailRootViewController = [detailViewController.viewControllers firstObject]; + UIViewController *detailRootViewController = detailViewController.viewControllers.firstObject; [detailRootViewController.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; } @@ -71,9 +71,9 @@ - (void)splitViewController:(UISplitViewController *)splitViewController willHid // This method is similar to the one above except that it removes the bar button on the detail view controller's root view controller // since the interface orientation is now portrait. - (void)splitViewController:(UISplitViewController *)splitViewController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem { - UINavigationController *detailViewController = [splitViewController.viewControllers lastObject]; + UINavigationController *detailViewController = splitViewController.viewControllers.lastObject; - UIViewController *detailRootViewController = [detailViewController.viewControllers firstObject]; + UIViewController *detailRootViewController = detailViewController.viewControllers.firstObject; [detailRootViewController.navigationItem setLeftBarButtonItem:nil animated:YES]; } diff --git a/Example/UICatalog/AAPLStepperViewController.m b/Example/UICatalog/AAPLStepperViewController.m index 9fb137cc88..24a49ae061 100644 --- a/Example/UICatalog/AAPLStepperViewController.m +++ b/Example/UICatalog/AAPLStepperViewController.m @@ -86,7 +86,7 @@ - (void)configureDefaultStepper { } - (void)configureTintedStepper { - self.tintedStepper.tintColor = [UIColor aapl_applicationBlueColor]; + self.tintedStepper.tintColor = UIColor.aapl_applicationBlueColor; self.tintedStepperLabel.text = [NSString stringWithFormat:@"%ld", (long)self.tintedStepper.value]; [self.tintedStepper addTarget:self action:@selector(stepperValueDidChange:) forControlEvents:UIControlEventValueChanged]; diff --git a/Example/UICatalog/AAPLSwitchViewController.m b/Example/UICatalog/AAPLSwitchViewController.m index 2af79b6077..f279d68cc5 100644 --- a/Example/UICatalog/AAPLSwitchViewController.m +++ b/Example/UICatalog/AAPLSwitchViewController.m @@ -76,9 +76,9 @@ - (void)configureDefaultSwitch { } - (void)configureTintedSwitch { - self.tintedSwitch.tintColor = [UIColor aapl_applicationBlueColor]; - self.tintedSwitch.onTintColor = [UIColor aapl_applicationGreenColor]; - self.tintedSwitch.thumbTintColor = [UIColor aapl_applicationPurpleColor]; + self.tintedSwitch.tintColor = UIColor.aapl_applicationBlueColor; + self.tintedSwitch.onTintColor = UIColor.aapl_applicationGreenColor; + self.tintedSwitch.thumbTintColor = UIColor.aapl_applicationPurpleColor; [self.tintedSwitch addTarget:self action:@selector(switchValueDidChange:) forControlEvents:UIControlEventValueChanged]; } diff --git a/Example/UICatalog/AAPLTextFieldViewController.m b/Example/UICatalog/AAPLTextFieldViewController.m index 1bdd3c9a71..aa8e4d6d6d 100644 --- a/Example/UICatalog/AAPLTextFieldViewController.m +++ b/Example/UICatalog/AAPLTextFieldViewController.m @@ -83,8 +83,8 @@ - (void)configureTextField { } - (void)configureTintedTextField { - self.tintedTextField.tintColor = [UIColor aapl_applicationBlueColor]; - self.tintedTextField.textColor = [UIColor aapl_applicationGreenColor]; + self.tintedTextField.tintColor = UIColor.aapl_applicationBlueColor; + self.tintedTextField.textColor = UIColor.aapl_applicationGreenColor; self.tintedTextField.placeholder = NSLocalizedString(@"Placeholder text", nil); self.tintedTextField.returnKeyType = UIReturnKeyDone; @@ -127,7 +127,7 @@ - (void)configureCustomTextField { // Add an empty view as the left view to ensure inset between the text and the bounding rectangle. UIView *leftPaddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 0)]; - leftPaddingView.backgroundColor = [UIColor clearColor]; + leftPaddingView.backgroundColor = UIColor.clearColor; self.customTextField.leftView = leftPaddingView; self.customTextField.leftViewMode = UITextFieldViewModeAlways; @@ -149,7 +149,7 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField { #pragma mark - Actions - (void)customTextFieldPurpleButtonClicked { - self.customTextField.textColor = [UIColor aapl_applicationPurpleColor]; + self.customTextField.textColor = UIColor.aapl_applicationPurpleColor; NSLog(@"The custom text field's purple right view button was clicked."); } diff --git a/Example/UICatalog/AAPLTextViewController.m b/Example/UICatalog/AAPLTextViewController.m index f3b1010eef..2844d504f0 100644 --- a/Example/UICatalog/AAPLTextViewController.m +++ b/Example/UICatalog/AAPLTextViewController.m @@ -71,15 +71,15 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // Listen for changes to keyboard visibility so that we can adjust the text view accordingly. - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + [NSNotificationCenter.defaultCenter removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [NSNotificationCenter.defaultCenter removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } @@ -135,8 +135,8 @@ - (void)configureTextView { UIFontDescriptor *bodyFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; self.textView.font = [UIFont fontWithDescriptor:bodyFontDescriptor size:0]; - self.textView.textColor = [UIColor blackColor]; - self.textView.backgroundColor = [UIColor whiteColor]; + self.textView.textColor = UIColor.blackColor; + self.textView.backgroundColor = UIColor.whiteColor; self.textView.scrollEnabled = YES; // Let's modify some of the attributes of the attributed string. @@ -158,13 +158,13 @@ - (void)configureTextView { [attributedText addAttribute:NSFontAttributeName value:boldFont range:boldRange]; // Add highlight. - [attributedText addAttribute:NSBackgroundColorAttributeName value:[UIColor aapl_applicationGreenColor] range:highlightedRange]; + [attributedText addAttribute:NSBackgroundColorAttributeName value:UIColor.aapl_applicationGreenColor range:highlightedRange]; // Add underline. [attributedText addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:underlinedRange]; // Add tint. - [attributedText addAttribute:NSForegroundColorAttributeName value:[UIColor aapl_applicationBlueColor] range:tintedRange]; + [attributedText addAttribute:NSForegroundColorAttributeName value:UIColor.aapl_applicationBlueColor range:tintedRange]; // Add an image attachment. NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; diff --git a/Example/UICatalog/AAPLTintedToolbarViewController.m b/Example/UICatalog/AAPLTintedToolbarViewController.m index ee108e2bd0..38bb596e62 100644 --- a/Example/UICatalog/AAPLTintedToolbarViewController.m +++ b/Example/UICatalog/AAPLTintedToolbarViewController.m @@ -71,8 +71,8 @@ - (void)configureToolbar { // See the UIBarStyle enum for more styles, including UIBarStyleDefault. self.toolbar.barStyle = UIBarStyleBlackTranslucent; - self.toolbar.tintColor = [UIColor aapl_applicationGreenColor]; - self.toolbar.backgroundColor = [UIColor aapl_applicationBlueColor]; + self.toolbar.tintColor = UIColor.aapl_applicationGreenColor; + self.toolbar.backgroundColor = UIColor.aapl_applicationBlueColor; NSArray *toolbarButtonItems = @[[self refreshBarButtonItem], [self flexibleSpaceBarButtonItem], [self actionBarButtonItem]]; [self.toolbar setItems:toolbarButtonItems animated:YES]; diff --git a/Example/UICatalog/AAPLWebViewController.m b/Example/UICatalog/AAPLWebViewController.m index d2403b5549..a99e1931e6 100644 --- a/Example/UICatalog/AAPLWebViewController.m +++ b/Example/UICatalog/AAPLWebViewController.m @@ -69,8 +69,8 @@ - (void)viewDidLoad { - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - if ([UIApplication sharedApplication].isNetworkActivityIndicatorVisible) { - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + if (UIApplication.sharedApplication.isNetworkActivityIndicatorVisible) { + UIApplication.sharedApplication.networkActivityIndicatorVisible = NO; } } @@ -84,7 +84,7 @@ - (void)loadAddressURL { #pragma mark - Configuration - (void)configureWebView { - self.webView.backgroundColor = [UIColor whiteColor]; + self.webView.backgroundColor = UIColor.whiteColor; self.webView.scalesPageToFit = YES; self.webView.dataDetectorTypes = UIDataDetectorTypeAll; } @@ -93,11 +93,11 @@ - (void)configureWebView { #pragma mark - UIWebViewDelegate - (void)webViewDidStartLoad:(UIWebView *)webView { - [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; + UIApplication.sharedApplication.networkActivityIndicatorVisible = YES; } - (void)webViewDidFinishLoad:(UIWebView *)webView { - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + UIApplication.sharedApplication.networkActivityIndicatorVisible = NO; } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { @@ -108,7 +108,7 @@ - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSString *errorHTML = [NSString stringWithFormat:errorFormatString, localizedErrorMessage, error.localizedDescription]; [self.webView loadHTMLString:errorHTML baseURL:nil]; - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + UIApplication.sharedApplication.networkActivityIndicatorVisible = NO; } From 81b7ccea2246e3251b2f5628685fd8e8c0acaeee Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Fri, 16 Aug 2019 12:48:34 -0500 Subject: [PATCH 05/45] Avoid using [[* alloc] init*] where possible Prefer shorthand initializers, like +new or +stringWithCString:encoding: --- .../FLEXArgumentInputColorView.m | 16 +++---- .../FLEXArgumentInputDateView.m | 2 +- .../FLEXArgumentInputSwitchView.m | 2 +- .../FLEXArgumentInputView.m | 2 +- Classes/Editing/FLEXFieldEditorView.m | 6 +-- .../Editing/FLEXFieldEditorViewController.m | 2 +- .../FLEXExplorerViewController.m | 6 +-- .../FLEXMultiColumnTableView.m | 10 ++-- .../FLEXRealmDatabaseManager.m | 2 +- .../FLEXTableListViewController.m | 2 +- .../FLEXLibrariesTableViewController.m | 2 +- .../FLEXLiveObjectsTableViewController.m | 2 +- .../SystemLog/FLEXSystemLogTableViewCell.m | 4 +- Classes/Manager/FLEXManager.m | 6 +-- Classes/Network/FLEXNetworkCurlLogger.m | 2 +- .../FLEXNetworkHistoryTableViewController.m | 4 +- Classes/Network/FLEXNetworkRecorder.m | 6 +-- .../FLEXNetworkSettingsTableViewController.m | 10 ++-- ...workTransactionDetailTableViewController.m | 48 +++++++++---------- .../FLEXNetworkTransactionTableViewCell.m | 10 ++-- .../PonyDebugger/FLEXNetworkObserver.m | 10 ++-- .../FLEXObjectExplorerViewController.m | 8 ++-- .../FLEXObjectExplorerFactory.m | 2 +- Classes/Toolbar/FLEXExplorerToolbar.m | 12 ++--- Classes/Utility/FLEXKeyboardShortcutManager.m | 4 +- Classes/Utility/FLEXRuntimeUtility.m | 2 +- Classes/Utility/FLEXUtility.m | 4 +- .../FLEXHierarchyTableViewCell.m | 4 +- Example/UICatalog/AAPLAppDelegate.m | 2 +- .../AAPLCatalogTableTableViewController.m | 4 +- Example/UICatalog/AAPLDatePickerController.m | 4 +- .../UICatalog/AAPLProgressViewController.m | 2 +- Example/UICatalog/AAPLTextViewController.m | 2 +- 33 files changed, 102 insertions(+), 102 deletions(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m index 801ca7512d..654d719a78 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m @@ -34,12 +34,12 @@ - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.slider = [[UISlider alloc] init]; + self.slider = [UISlider new]; self.slider.backgroundColor = self.backgroundColor; [self.slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged]; [self addSubview:self.slider]; - self.valueLabel = [[UILabel alloc] init]; + self.valueLabel = [UILabel new]; self.valueLabel.backgroundColor = self.backgroundColor; self.valueLabel.font = [FLEXUtility defaultFontOfSize:14.0]; self.valueLabel.textAlignment = NSTextAlignmentRight; @@ -168,31 +168,31 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { self = [super initWithArgumentTypeEncoding:typeEncoding]; if (self) { - self.colorPreviewBox = [[FLEXColorPreviewBox alloc] init]; + self.colorPreviewBox = [FLEXColorPreviewBox new]; [self addSubview:self.colorPreviewBox]; - self.hexLabel = [[UILabel alloc] init]; + self.hexLabel = [UILabel new]; self.hexLabel.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9]; self.hexLabel.textAlignment = NSTextAlignmentCenter; self.hexLabel.font = [FLEXUtility defaultFontOfSize:12.0]; [self addSubview:self.hexLabel]; - self.alphaInput = [[FLEXColorComponentInputView alloc] init]; + self.alphaInput = [FLEXColorComponentInputView new]; self.alphaInput.slider.minimumTrackTintColor = UIColor.blackColor; self.alphaInput.delegate = self; [self addSubview:self.alphaInput]; - self.redInput = [[FLEXColorComponentInputView alloc] init]; + self.redInput = [FLEXColorComponentInputView new]; self.redInput.slider.minimumTrackTintColor = UIColor.redColor; self.redInput.delegate = self; [self addSubview:self.redInput]; - self.greenInput = [[FLEXColorComponentInputView alloc] init]; + self.greenInput = [FLEXColorComponentInputView new]; self.greenInput.slider.minimumTrackTintColor = UIColor.greenColor; self.greenInput.delegate = self; [self addSubview:self.greenInput]; - self.blueInput = [[FLEXColorComponentInputView alloc] init]; + self.blueInput = [FLEXColorComponentInputView new]; self.blueInput.slider.minimumTrackTintColor = UIColor.blueColor; self.blueInput.delegate = self; [self addSubview:self.blueInput]; diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m index 0907d216be..2efbab4be6 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m @@ -21,7 +21,7 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { self = [super initWithArgumentTypeEncoding:typeEncoding]; if (self) { - self.datePicker = [[UIDatePicker alloc] init]; + self.datePicker = [UIDatePicker new]; self.datePicker.datePickerMode = UIDatePickerModeDateAndTime; // Using UTC, because that's what the NSDate description prints self.datePicker.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m index b5ee840a01..48edfc4e99 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m @@ -20,7 +20,7 @@ - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { self = [super initWithArgumentTypeEncoding:typeEncoding]; if (self) { - self.inputSwitch = [[UISwitch alloc] init]; + self.inputSwitch = [UISwitch new]; [self.inputSwitch addTarget:self action:@selector(switchValueDidChange:) forControlEvents:UIControlEventValueChanged]; [self.inputSwitch sizeToFit]; [self addSubview:self.inputSwitch]; diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m index 9136916eb3..22f7f9cf01 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m @@ -56,7 +56,7 @@ - (void)setTitle:(NSString *)title - (UILabel *)titleLabel { if (!_titleLabel) { - _titleLabel = [[UILabel alloc] init]; + _titleLabel = [UILabel new]; _titleLabel.font = [[self class] titleFont]; _titleLabel.backgroundColor = self.backgroundColor; _titleLabel.textColor = [UIColor colorWithWhite:0.3 alpha:1.0]; diff --git a/Classes/Editing/FLEXFieldEditorView.m b/Classes/Editing/FLEXFieldEditorView.m index b8fb5ef68f..5fa9981f3d 100644 --- a/Classes/Editing/FLEXFieldEditorView.m +++ b/Classes/Editing/FLEXFieldEditorView.m @@ -25,7 +25,7 @@ - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.targetDescriptionLabel = [[UILabel alloc] init]; + self.targetDescriptionLabel = [UILabel new]; self.targetDescriptionLabel.numberOfLines = 0; self.targetDescriptionLabel.font = [[self class] labelFont]; [self addSubview:self.targetDescriptionLabel]; @@ -33,7 +33,7 @@ - (id)initWithFrame:(CGRect)frame self.targetDescriptionDivider = [[self class] dividerView]; [self addSubview:self.targetDescriptionDivider]; - self.fieldDescriptionLabel = [[UILabel alloc] init]; + self.fieldDescriptionLabel = [UILabel new]; self.fieldDescriptionLabel.numberOfLines = 0; self.fieldDescriptionLabel.font = [[self class] labelFont]; [self addSubview:self.fieldDescriptionLabel]; @@ -123,7 +123,7 @@ - (void)setArgumentInputViews:(NSArray *)argumentInputV + (UIView *)dividerView { - UIView *dividerView = [[UIView alloc] init]; + UIView *dividerView = [UIView new]; dividerView.backgroundColor = [self dividerColor]; return dividerView; } diff --git a/Classes/Editing/FLEXFieldEditorViewController.m b/Classes/Editing/FLEXFieldEditorViewController.m index 38b03e71e6..69223f2640 100644 --- a/Classes/Editing/FLEXFieldEditorViewController.m +++ b/Classes/Editing/FLEXFieldEditorViewController.m @@ -83,7 +83,7 @@ - (void)viewDidLoad self.scrollView.delegate = self; [self.view addSubview:self.scrollView]; - self.fieldEditorView = [[FLEXFieldEditorView alloc] init]; + self.fieldEditorView = [FLEXFieldEditorView new]; self.fieldEditorView.backgroundColor = self.view.backgroundColor; self.fieldEditorView.targetDescription = [NSString stringWithFormat:@"%@ %p", [self.target class], self.target]; [self.scrollView addSubview:self.fieldEditorView]; diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index b5925f14a2..b3d043a6af 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -95,7 +95,7 @@ - (void)viewDidLoad [super viewDidLoad]; // Toolbar - self.explorerToolbar = [[FLEXExplorerToolbar alloc] init]; + self.explorerToolbar = [FLEXExplorerToolbar new]; // Start the toolbar off below any bars that may be at the top of the view. id toolbarOriginYDefault = [[NSUserDefaults standardUserDefaults] objectForKey:kFLEXToolbarTopMarginDefaultsKey]; @@ -215,7 +215,7 @@ - (void)setSelectedView:(UIView *)selectedView if (selectedView) { if (!self.selectedViewOverlay) { - self.selectedViewOverlay = [[UIView alloc] init]; + self.selectedViewOverlay = [UIView new]; [self.view addSubview:self.selectedViewOverlay]; self.selectedViewOverlay.layer.borderWidth = 1.0; } @@ -883,7 +883,7 @@ - (void)toggleViewsToolWithCompletion:(void(^)(void))completion - (void)toggleMenuTool { [self toggleToolWithViewControllerProvider:^UIViewController *{ - FLEXGlobalsTableViewController *globalsViewController = [[FLEXGlobalsTableViewController alloc] init]; + FLEXGlobalsTableViewController *globalsViewController = [FLEXGlobalsTableViewController new]; globalsViewController.delegate = self; [FLEXGlobalsTableViewController setApplicationWindow:[UIApplication.sharedApplication keyWindow]]; return [[UINavigationController alloc] initWithRootViewController:globalsViewController]; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m index 994ae3ba4e..28b2d4957a 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m @@ -91,7 +91,7 @@ - (void)reloadData - (void)loadHeaderScrollView { - UIScrollView *headerScrollView = [[UIScrollView alloc] init]; + UIScrollView *headerScrollView = [UIScrollView new]; headerScrollView.delegate = self; self.headerScrollView = headerScrollView; self.headerScrollView.backgroundColor = [UIColor colorWithWhite:0.803 alpha:0.850]; @@ -102,11 +102,11 @@ - (void)loadHeaderScrollView - (void)loadContentScrollView { - UIScrollView *scrollView = [[UIScrollView alloc] init]; + UIScrollView *scrollView = [UIScrollView new]; scrollView.bounces = NO; scrollView.delegate = self; - UITableView *tableView = [[UITableView alloc] init]; + UITableView *tableView = [UITableView new]; tableView.delegate = self; tableView.dataSource = self; tableView.separatorStyle = UITableViewCellSeparatorStyleNone; @@ -121,14 +121,14 @@ - (void)loadContentScrollView - (void)loadLeftView { - UITableView *leftTableView = [[UITableView alloc] init]; + UITableView *leftTableView = [UITableView new]; leftTableView.delegate = self; leftTableView.dataSource = self; leftTableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.leftTableView = leftTableView; [self addSubview:leftTableView]; - UIView *leftHeader = [[UIView alloc] init]; + UIView *leftHeader = [UIView new]; leftHeader.backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.668]; self.leftHeader = leftHeader; [self addSubview:leftHeader]; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m index 390c393ecd..605002ee47 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m @@ -51,7 +51,7 @@ - (BOOL)open } NSError *error = nil; - id configuration = [[configurationClass alloc] init]; + id configuration = [configurationClass new]; [(RLMRealmConfiguration *)configuration setFileURL:[NSURL fileURLWithPath:self.path]]; self.realm = [realmClass realmWithConfiguration:configuration error:&error]; return (error == nil); diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m index 1121cb4d79..5d7a1969a4 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m @@ -88,7 +88,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXTableContentViewController *contentViewController = [[FLEXTableContentViewController alloc] init]; + FLEXTableContentViewController *contentViewController = [FLEXTableContentViewController new]; contentViewController.contentsArray = [_dbm queryAllDataWithTableName:self.tables[indexPath.row]]; contentViewController.columnsArray = [_dbm queryAllColumnsWithTableName:self.tables[indexPath.row]]; diff --git a/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m b/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m index c49a739c8c..6f3d9926dc 100644 --- a/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m @@ -172,7 +172,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath objectExplorer.object = self.foundClass; [self.navigationController pushViewController:objectExplorer animated:YES]; } else { - FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init]; + FLEXClassesTableViewController *classesViewController = [FLEXClassesTableViewController new]; classesViewController.binaryImageName = self.filteredImageNames[self.foundClass ? indexPath.row-1 : indexPath.row]; [self.navigationController pushViewController:classesViewController animated:YES]; } diff --git a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m index a9bbf76d40..f1586bd796 100644 --- a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m @@ -37,7 +37,7 @@ - (void)viewDidLoad self.showsCarousel = YES; self.carousel.items = @[@"A→Z", @"Count", @"Size"]; - self.refreshControl = [[UIRefreshControl alloc] init]; + self.refreshControl = [UIRefreshControl new]; [self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged]; [self reloadTableData]; diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m index 84e80d7365..6516232343 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m @@ -24,7 +24,7 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStr { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { - self.logMessageLabel = [[UILabel alloc] init]; + self.logMessageLabel = [UILabel new]; self.logMessageLabel.numberOfLines = 0; self.separatorInset = UIEdgeInsetsZero; self.selectionStyle = UITableViewCellSelectionStyleNone; @@ -118,7 +118,7 @@ + (NSString *)logTimeStringFromDate:(NSDate *)date static NSDateFormatter *formatter = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - formatter = [[NSDateFormatter alloc] init]; + formatter = [NSDateFormatter new]; formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; }); diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 3e2e038008..259c359874 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -37,7 +37,7 @@ + (instancetype)sharedManager static FLEXManager *sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedManager = [[[self class] alloc] init]; + sharedManager = [self new]; }); return sharedManager; } @@ -68,7 +68,7 @@ - (FLEXWindow *)explorerWindow - (FLEXExplorerViewController *)explorerViewController { if (!_explorerViewController) { - _explorerViewController = [[FLEXExplorerViewController alloc] init]; + _explorerViewController = [FLEXExplorerViewController new]; _explorerViewController.delegate = self; } @@ -393,7 +393,7 @@ - (void)toggleTopViewControllerOfClass:(Class)class { [[topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; } else { - id viewController = [[class alloc] init]; + id viewController = [class new]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; [topViewController presentViewController:navigationController animated:YES completion:nil]; } diff --git a/Classes/Network/FLEXNetworkCurlLogger.m b/Classes/Network/FLEXNetworkCurlLogger.m index 2bc6088d8f..d8680ec79a 100644 --- a/Classes/Network/FLEXNetworkCurlLogger.m +++ b/Classes/Network/FLEXNetworkCurlLogger.m @@ -28,7 +28,7 @@ + (NSString *)curlCommandString:(NSURLRequest *)request { } if (request.HTTPBody) { - [curlCommandString appendFormat:@"-d \'%@\'", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]]; + [curlCommandString appendFormat:@"-d \'%@\'", [NSString stringWithCString:request.HTTPBody.bytes encoding:NSUTF8StringEncoding]]; } return curlCommandString; diff --git a/Classes/Network/FLEXNetworkHistoryTableViewController.m b/Classes/Network/FLEXNetworkHistoryTableViewController.m index a031f5854d..2a85ac8e70 100644 --- a/Classes/Network/FLEXNetworkHistoryTableViewController.m +++ b/Classes/Network/FLEXNetworkHistoryTableViewController.m @@ -68,7 +68,7 @@ - (void)viewDidLoad - (void)settingsButtonTapped:(id)sender { - FLEXNetworkSettingsTableViewController *settingsViewController = [[FLEXNetworkSettingsTableViewController alloc] init]; + FLEXNetworkSettingsTableViewController *settingsViewController = [FLEXNetworkSettingsTableViewController new]; settingsViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(settingsViewControllerDoneTapped:)]; settingsViewController.title = @"Network Debugging Settings"; UINavigationController *wrapperNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; @@ -293,7 +293,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXNetworkTransactionDetailTableViewController *detailViewController = [[FLEXNetworkTransactionDetailTableViewController alloc] init]; + FLEXNetworkTransactionDetailTableViewController *detailViewController = [FLEXNetworkTransactionDetailTableViewController new]; detailViewController.transaction = [self transactionAtIndexPath:indexPath inTableView:tableView]; [self.navigationController pushViewController:detailViewController animated:YES]; } diff --git a/Classes/Network/FLEXNetworkRecorder.m b/Classes/Network/FLEXNetworkRecorder.m index 898eada888..b685286c22 100644 --- a/Classes/Network/FLEXNetworkRecorder.m +++ b/Classes/Network/FLEXNetworkRecorder.m @@ -34,7 +34,7 @@ - (instancetype)init { self = [super init]; if (self) { - self.responseCache = [[NSCache alloc] init]; + self.responseCache = [NSCache new]; NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey] unsignedIntegerValue]; if (responseCacheLimit) { [self.responseCache setTotalCostLimit:responseCacheLimit]; @@ -56,7 +56,7 @@ + (instancetype)defaultRecorder static FLEXNetworkRecorder *defaultRecorder = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - defaultRecorder = [[[self class] alloc] init]; + defaultRecorder = [self new]; }); return defaultRecorder; } @@ -118,7 +118,7 @@ - (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSUR } dispatch_async(self.queue, ^{ - FLEXNetworkTransaction *transaction = [[FLEXNetworkTransaction alloc] init]; + FLEXNetworkTransaction *transaction = [FLEXNetworkTransaction new]; transaction.requestID = requestID; transaction.request = request; transaction.startTime = startDate; diff --git a/Classes/Network/FLEXNetworkSettingsTableViewController.m b/Classes/Network/FLEXNetworkSettingsTableViewController.m index d8791c54e8..6c92f35b4e 100644 --- a/Classes/Network/FLEXNetworkSettingsTableViewController.m +++ b/Classes/Network/FLEXNetworkSettingsTableViewController.m @@ -108,12 +108,12 @@ - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger - (UITableViewCell *)switchCellWithTitle:(NSString *)title toggleAction:(SEL)toggleAction isOn:(BOOL)isOn { - UITableViewCell *cell = [[UITableViewCell alloc] init]; + UITableViewCell *cell = [UITableViewCell new]; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.text = title; cell.textLabel.font = [[self class] cellTitleFont]; - UISwitch *theSwitch = [[UISwitch alloc] init]; + UISwitch *theSwitch = [UISwitch new]; theSwitch.on = isOn; [theSwitch addTarget:self action:toggleAction forControlEvents:UIControlEventValueChanged]; @@ -128,7 +128,7 @@ - (UITableViewCell *)switchCellWithTitle:(NSString *)title toggleAction:(SEL)tog - (UITableViewCell *)buttonCellWithTitle:(NSString *)title touchUpAction:(SEL)action isDestructive:(BOOL)isDestructive { - UITableViewCell *buttonCell = [[UITableViewCell alloc] init]; + UITableViewCell *buttonCell = [UITableViewCell new]; buttonCell.selectionStyle = UITableViewCellSelectionStyleNone; UIButton *actionButton = [UIButton buttonWithType:UIButtonTypeSystem]; @@ -156,12 +156,12 @@ - (NSString *)titleForCacheLimitCellWithValue:(long long)cacheLimit - (UITableViewCell *)sliderCellWithTitle:(NSString *)title changedAction:(SEL)changedAction minimum:(CGFloat)minimum maximum:(CGFloat)maximum initialValue:(CGFloat)initialValue { - UITableViewCell *sliderCell = [[UITableViewCell alloc] init]; + UITableViewCell *sliderCell = [UITableViewCell new]; sliderCell.selectionStyle = UITableViewCellSelectionStyleNone; sliderCell.textLabel.text = title; sliderCell.textLabel.font = [[self class] cellTitleFont]; - UISlider *slider = [[UISlider alloc] init]; + UISlider *slider = [UISlider new]; slider.minimumValue = minimum; slider.maximumValue = maximum; slider.value = initialValue; diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m index 988675b904..4664dcdbaa 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m @@ -219,7 +219,7 @@ + (NSAttributedString *)attributedTextForRow:(FLEXNetworkDetailRow *)row NSString *title = [NSString stringWithFormat:@"%@: ", row.title]; NSString *detailText = row.detailText ?: @""; - NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init]; + NSMutableAttributedString *attributedText = [NSMutableAttributedString new]; [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:title attributes:titleAttributes]]; [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:detailText attributes:detailAttributes]]; @@ -232,7 +232,7 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti { NSMutableArray *rows = [NSMutableArray array]; - FLEXNetworkDetailRow *requestURLRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *requestURLRow = [FLEXNetworkDetailRow new]; requestURLRow.title = @"Request URL"; NSURL *url = transaction.request.URL; requestURLRow.detailText = url.absoluteString; @@ -243,18 +243,18 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti }; [rows addObject:requestURLRow]; - FLEXNetworkDetailRow *requestMethodRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *requestMethodRow = [FLEXNetworkDetailRow new]; requestMethodRow.title = @"Request Method"; requestMethodRow.detailText = transaction.request.HTTPMethod; [rows addObject:requestMethodRow]; if (transaction.cachedRequestBody.length > 0) { - FLEXNetworkDetailRow *postBodySizeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *postBodySizeRow = [FLEXNetworkDetailRow new]; postBodySizeRow.title = @"Request Body Size"; postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.cachedRequestBody.length countStyle:NSByteCountFormatterCountStyleBinary]; [rows addObject:postBodySizeRow]; - FLEXNetworkDetailRow *postBodyRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *postBodyRow = [FLEXNetworkDetailRow new]; postBodyRow.title = @"Request Body"; postBodyRow.detailText = @"tap to view"; postBodyRow.selectionFuture = ^{ @@ -273,20 +273,20 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:transaction.response]; if (statusCodeString.length > 0) { - FLEXNetworkDetailRow *statusCodeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *statusCodeRow = [FLEXNetworkDetailRow new]; statusCodeRow.title = @"Status Code"; statusCodeRow.detailText = statusCodeString; [rows addObject:statusCodeRow]; } if (transaction.error) { - FLEXNetworkDetailRow *errorRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *errorRow = [FLEXNetworkDetailRow new]; errorRow.title = @"Error"; errorRow.detailText = transaction.error.localizedDescription; [rows addObject:errorRow]; } - FLEXNetworkDetailRow *responseBodyRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *responseBodyRow = [FLEXNetworkDetailRow new]; responseBodyRow.title = @"Response Body"; NSData *responseData = [[FLEXNetworkRecorder defaultRecorder] cachedResponseBodyForTransaction:transaction]; if (responseData.length > 0) { @@ -315,52 +315,52 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti } [rows addObject:responseBodyRow]; - FLEXNetworkDetailRow *responseSizeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *responseSizeRow = [FLEXNetworkDetailRow new]; responseSizeRow.title = @"Response Size"; responseSizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.receivedDataLength countStyle:NSByteCountFormatterCountStyleBinary]; [rows addObject:responseSizeRow]; - FLEXNetworkDetailRow *mimeTypeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *mimeTypeRow = [FLEXNetworkDetailRow new]; mimeTypeRow.title = @"MIME Type"; mimeTypeRow.detailText = transaction.response.MIMEType; [rows addObject:mimeTypeRow]; - FLEXNetworkDetailRow *mechanismRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *mechanismRow = [FLEXNetworkDetailRow new]; mechanismRow.title = @"Mechanism"; mechanismRow.detailText = transaction.requestMechanism; [rows addObject:mechanismRow]; - NSDateFormatter *startTimeFormatter = [[NSDateFormatter alloc] init]; + NSDateFormatter *startTimeFormatter = [NSDateFormatter new]; startTimeFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; - FLEXNetworkDetailRow *localStartTimeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *localStartTimeRow = [FLEXNetworkDetailRow new]; localStartTimeRow.title = [NSString stringWithFormat:@"Start Time (%@)", [[NSTimeZone localTimeZone] abbreviationForDate:transaction.startTime]]; localStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime]; [rows addObject:localStartTimeRow]; startTimeFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; - FLEXNetworkDetailRow *utcStartTimeRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *utcStartTimeRow = [FLEXNetworkDetailRow new]; utcStartTimeRow.title = @"Start Time (UTC)"; utcStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime]; [rows addObject:utcStartTimeRow]; - FLEXNetworkDetailRow *unixStartTime = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *unixStartTime = [FLEXNetworkDetailRow new]; unixStartTime.title = @"Unix Start Time"; unixStartTime.detailText = [NSString stringWithFormat:@"%f", [transaction.startTime timeIntervalSince1970]]; [rows addObject:unixStartTime]; - FLEXNetworkDetailRow *durationRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *durationRow = [FLEXNetworkDetailRow new]; durationRow.title = @"Total Duration"; durationRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.duration]; [rows addObject:durationRow]; - FLEXNetworkDetailRow *latencyRow = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *latencyRow = [FLEXNetworkDetailRow new]; latencyRow.title = @"Latency"; latencyRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.latency]; [rows addObject:latencyRow]; - FLEXNetworkDetailSection *generalSection = [[FLEXNetworkDetailSection alloc] init]; + FLEXNetworkDetailSection *generalSection = [FLEXNetworkDetailSection new]; generalSection.title = @"General"; generalSection.rows = rows; @@ -369,7 +369,7 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti + (FLEXNetworkDetailSection *)requestHeadersSectionForTransaction:(FLEXNetworkTransaction *)transaction { - FLEXNetworkDetailSection *requestHeadersSection = [[FLEXNetworkDetailSection alloc] init]; + FLEXNetworkDetailSection *requestHeadersSection = [FLEXNetworkDetailSection new]; requestHeadersSection.title = @"Request Headers"; requestHeadersSection.rows = [self networkDetailRowsFromDictionary:transaction.request.allHTTPHeaderFields]; @@ -378,12 +378,12 @@ + (FLEXNetworkDetailSection *)requestHeadersSectionForTransaction:(FLEXNetworkTr + (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransaction *)transaction { - FLEXNetworkDetailSection *postBodySection = [[FLEXNetworkDetailSection alloc] init]; + FLEXNetworkDetailSection *postBodySection = [FLEXNetworkDetailSection new]; postBodySection.title = @"Request Body Parameters"; if (transaction.cachedRequestBody.length > 0) { NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; if ([contentType hasPrefix:@"application/x-www-form-urlencoded"]) { - NSString *bodyString = [[NSString alloc] initWithData:[self postBodyDataForTransaction:transaction] encoding:NSUTF8StringEncoding]; + NSString *bodyString = [NSString stringWithCString:[self postBodyDataForTransaction:transaction].bytes encoding:NSUTF8StringEncoding]; postBodySection.rows = [self networkDetailRowsFromDictionary:[FLEXUtility dictionaryFromQuery:bodyString]]; } } @@ -393,7 +393,7 @@ + (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransact + (FLEXNetworkDetailSection *)queryParametersSectionForTransaction:(FLEXNetworkTransaction *)transaction { NSDictionary *queryDictionary = [FLEXUtility dictionaryFromQuery:transaction.request.URL.query]; - FLEXNetworkDetailSection *querySection = [[FLEXNetworkDetailSection alloc] init]; + FLEXNetworkDetailSection *querySection = [FLEXNetworkDetailSection new]; querySection.title = @"Query Parameters"; querySection.rows = [self networkDetailRowsFromDictionary:queryDictionary]; @@ -402,7 +402,7 @@ + (FLEXNetworkDetailSection *)queryParametersSectionForTransaction:(FLEXNetworkT + (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkTransaction *)transaction { - FLEXNetworkDetailSection *responseHeadersSection = [[FLEXNetworkDetailSection alloc] init]; + FLEXNetworkDetailSection *responseHeadersSection = [FLEXNetworkDetailSection new]; responseHeadersSection.title = @"Response Headers"; if ([transaction.response isKindOfClass:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)transaction.response; @@ -417,7 +417,7 @@ + (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkT NSArray *sortedKeys = [dictionary.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; for (NSString *key in sortedKeys) { id value = dictionary[key]; - FLEXNetworkDetailRow *row = [[FLEXNetworkDetailRow alloc] init]; + FLEXNetworkDetailRow *row = [FLEXNetworkDetailRow new]; row.title = key; row.detailText = [value description]; [rows addObject:row]; diff --git a/Classes/Network/FLEXNetworkTransactionTableViewCell.m b/Classes/Network/FLEXNetworkTransactionTableViewCell.m index 63688e21aa..cdbfe3a2e9 100644 --- a/Classes/Network/FLEXNetworkTransactionTableViewCell.m +++ b/Classes/Network/FLEXNetworkTransactionTableViewCell.m @@ -31,22 +31,22 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStr if (self) { self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - self.nameLabel = [[UILabel alloc] init]; + self.nameLabel = [UILabel new]; self.nameLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; [self.contentView addSubview:self.nameLabel]; - self.pathLabel = [[UILabel alloc] init]; + self.pathLabel = [UILabel new]; self.pathLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; self.pathLabel.textColor = [UIColor colorWithWhite:0.4 alpha:1.0]; [self.contentView addSubview:self.pathLabel]; - self.thumbnailImageView = [[UIImageView alloc] init]; + self.thumbnailImageView = [UIImageView new]; self.thumbnailImageView.layer.borderColor = UIColor.blackColor.CGColor; self.thumbnailImageView.layer.borderWidth = 1.0; self.thumbnailImageView.contentMode = UIViewContentModeScaleAspectFit; [self.contentView addSubview:self.thumbnailImageView]; - self.transactionDetailsLabel = [[UILabel alloc] init]; + self.transactionDetailsLabel = [UILabel new]; self.transactionDetailsLabel.font = [FLEXUtility defaultFontOfSize:10.0]; self.transactionDetailsLabel.textColor = [UIColor colorWithWhite:0.65 alpha:1.0]; [self.contentView addSubview:self.transactionDetailsLabel]; @@ -167,7 +167,7 @@ + (NSString *)timestampStringFromRequestDate:(NSDate *)date static NSDateFormatter *dateFormatter = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter = [NSDateFormatter new]; dateFormatter.dateFormat = @"HH:mm:ss"; }); return [dateFormatter stringFromDate:date]; diff --git a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m index a57b8b446d..b157428c48 100644 --- a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m +++ b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m @@ -116,7 +116,7 @@ + (instancetype)sharedObserver static FLEXNetworkObserver *sharedObserver = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedObserver = [[[self class] alloc] init]; + sharedObserver = [self new]; }); return sharedObserver; } @@ -888,7 +888,7 @@ - (id)init { self = [super init]; if (self) { - self.requestStatesForRequestIDs = [[NSMutableDictionary alloc] init]; + self.requestStatesForRequestIDs = [NSMutableDictionary new]; self.queue = dispatch_queue_create("com.flex.FLEXNetworkObserver", DISPATCH_QUEUE_SERIAL); } return self; @@ -907,7 +907,7 @@ - (FLEXInternalRequestState *)requestStateForRequestID:(NSString *)requestID { FLEXInternalRequestState *requestState = self.requestStatesForRequestIDs[requestID]; if (!requestState) { - requestState = [[FLEXInternalRequestState alloc] init]; + requestState = [FLEXInternalRequestState new]; [self.requestStatesForRequestIDs setObject:requestState forKey:requestID]; } return requestState; @@ -943,7 +943,7 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon NSMutableData *dataAccumulator = nil; if (response.expectedContentLength < 0) { - dataAccumulator = [[NSMutableData alloc] init]; + dataAccumulator = [NSMutableData new]; } else if (response.expectedContentLength < 52428800) { dataAccumulator = [[NSMutableData alloc] initWithCapacity:(NSUInteger)response.expectedContentLength]; } @@ -1022,7 +1022,7 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data NSMutableData *dataAccumulator = nil; if (response.expectedContentLength < 0) { - dataAccumulator = [[NSMutableData alloc] init]; + dataAccumulator = [NSMutableData new]; } else { dataAccumulator = [[NSMutableData alloc] initWithCapacity:(NSUInteger)response.expectedContentLength]; } diff --git a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m index 53d725309e..83906365e3 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m @@ -97,7 +97,7 @@ - (void)viewDidLoad self.showsCarousel = YES; [self refreshScopeTitles]; - self.refreshControl = [[UIRefreshControl alloc] init]; + self.refreshControl = [UIRefreshControl new]; [self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged]; } @@ -245,7 +245,7 @@ - (void)updateMetadata objc_property_t *propertyList = class_copyPropertyList(class, &propertyCount); if (propertyList) { for (unsigned int i = 0; i < propertyCount; i++) { - FLEXPropertyBox *propertyBox = [[FLEXPropertyBox alloc] init]; + FLEXPropertyBox *propertyBox = [FLEXPropertyBox new]; propertyBox.property = propertyList[i]; [boxedProperties addObject:propertyBox]; } @@ -321,7 +321,7 @@ - (id)valueForPropertyAtIndex:(NSInteger)index Ivar *ivarList = class_copyIvarList(class, &ivarCount); if (ivarList) { for (unsigned int i = 0; i < ivarCount; i++) { - FLEXIvarBox *ivarBox = [[FLEXIvarBox alloc] init]; + FLEXIvarBox *ivarBox = [FLEXIvarBox new]; ivarBox.ivar = ivarList[i]; [boxedIvars addObject:ivarBox]; } @@ -409,7 +409,7 @@ - (void)updateFilteredClassMethods Method *methodList = class_copyMethodList(class, &methodCount); if (methodList) { for (unsigned int i = 0; i < methodCount; i++) { - FLEXMethodBox *methodBox = [[FLEXMethodBox alloc] init]; + FLEXMethodBox *methodBox = [FLEXMethodBox new]; methodBox.method = methodList[i]; [boxedMethods addObject:methodBox]; } diff --git a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m index 2be6af35c6..7fc80296f6 100644 --- a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m +++ b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m @@ -61,7 +61,7 @@ + (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object } } - FLEXObjectExplorerViewController *explorerViewController = [[explorerClass alloc] init]; + FLEXObjectExplorerViewController *explorerViewController = [explorerClass new]; explorerViewController.object = object; return explorerViewController; diff --git a/Classes/Toolbar/FLEXExplorerToolbar.m b/Classes/Toolbar/FLEXExplorerToolbar.m index b7876e66c7..e77a9a1ca7 100644 --- a/Classes/Toolbar/FLEXExplorerToolbar.m +++ b/Classes/Toolbar/FLEXExplorerToolbar.m @@ -38,11 +38,11 @@ - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.backgroundView = [[UIView alloc] init]; + self.backgroundView = [UIView new]; self.backgroundView.backgroundColor = [FLEXColor secondaryBackgroundColorWithAlpha:0.95]; [self addSubview:self.backgroundView]; - self.dragHandle = [[UIView alloc] init]; + self.dragHandle = [UIView new]; self.dragHandle.backgroundColor = UIColor.clearColor; [self addSubview:self.dragHandle]; @@ -66,20 +66,20 @@ - (id)initWithFrame:(CGRect)frame UIImage *closeIcon = [FLEXResources closeIcon]; self.closeItem = [FLEXToolbarItem toolbarItemWithTitle:@"close" image:closeIcon]; - self.selectedViewDescriptionContainer = [[UIView alloc] init]; + self.selectedViewDescriptionContainer = [UIView new]; self.selectedViewDescriptionContainer.backgroundColor = [FLEXColor tertiaryBackgroundColorWithAlpha:0.95]; self.selectedViewDescriptionContainer.hidden = YES; [self addSubview:self.selectedViewDescriptionContainer]; - self.selectedViewDescriptionSafeAreaContainer = [[UIView alloc] init]; + self.selectedViewDescriptionSafeAreaContainer = [UIView new]; self.selectedViewDescriptionSafeAreaContainer.backgroundColor = UIColor.clearColor; [self.selectedViewDescriptionContainer addSubview:self.selectedViewDescriptionSafeAreaContainer]; - self.selectedViewColorIndicator = [[UIView alloc] init]; + self.selectedViewColorIndicator = [UIView new]; self.selectedViewColorIndicator.backgroundColor = UIColor.redColor; [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewColorIndicator]; - self.selectedViewDescriptionLabel = [[UILabel alloc] init]; + self.selectedViewDescriptionLabel = [UILabel new]; self.selectedViewDescriptionLabel.backgroundColor = UIColor.clearColor; self.selectedViewDescriptionLabel.font = [[self class] descriptionLabelFont]; [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewDescriptionLabel]; diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.m b/Classes/Utility/FLEXKeyboardShortcutManager.m index 101dd86f5e..744bbfa81a 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.m +++ b/Classes/Utility/FLEXKeyboardShortcutManager.m @@ -100,7 +100,7 @@ + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags helpDescription:(NSString *)helpDescription { - FLEXKeyInput *keyInput = [[self alloc] init]; + FLEXKeyInput *keyInput = [self new]; if (keyInput) { keyInput->_key = key; keyInput->_flags = flags; @@ -128,7 +128,7 @@ + (instancetype)sharedManager static FLEXKeyboardShortcutManager *sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedManager = [[[self class] alloc] init]; + sharedManager = [self new]; }); return sharedManager; } diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index f3c6ce0061..7769ea695c 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -553,7 +553,7 @@ + (id)objectValueFromEditableJSONString:(NSString *)string + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString { - NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + NSNumberFormatter *formatter = [NSNumberFormatter new]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; NSNumber *number = [formatter numberFromString:inputString]; diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index c1773c8d95..0a38362117 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -322,11 +322,11 @@ + (NSString *)prettyJSONStringFromData:(NSData *)data id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; if ([NSJSONSerialization isValidJSONObject:jsonObject]) { - prettyString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:NULL] encoding:NSUTF8StringEncoding]; + prettyString = [NSString stringWithCString:[NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:NULL].bytes encoding:NSUTF8StringEncoding]; // NSJSONSerialization escapes forward slashes. We want pretty json, so run through and unescape the slashes. prettyString = [prettyString stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]; } else { - prettyString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + prettyString = [NSString stringWithCString:data.bytes encoding:NSUTF8StringEncoding]; } return prettyString; diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m index 9befa6c1d3..7ac85fec33 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m @@ -27,7 +27,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { - self.depthIndicatorView = [[UIView alloc] init]; + self.depthIndicatorView = [UIView new]; self.depthIndicatorView.backgroundColor = [FLEXUtility hierarchyIndentPatternColor]; [self.contentView addSubview:self.depthIndicatorView]; @@ -39,7 +39,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus self.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; self.accessoryType = UITableViewCellAccessoryDetailButton; - self.viewBackgroundColorView = [[UIView alloc] init]; + self.viewBackgroundColorView = [UIView new]; self.viewBackgroundColorView.clipsToBounds = YES; self.viewBackgroundColorView.layer.borderColor = UIColor.blackColor.CGColor; self.viewBackgroundColorView.layer.borderWidth = 1.0f; diff --git a/Example/UICatalog/AAPLAppDelegate.m b/Example/UICatalog/AAPLAppDelegate.m index 518bbd9c56..b3f6fb38fb 100644 --- a/Example/UICatalog/AAPLAppDelegate.m +++ b/Example/UICatalog/AAPLAppDelegate.m @@ -169,7 +169,7 @@ - (void)sendExampleNetworkRequests for (NSString *urlString in requestURLStrings) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]; - [self.connections addObject:[[NSURLConnection alloc] initWithRequest:request delegate:self]]; + [self.connections addObject:[NSURLConnection connectionWithRequest:request delegate:self]]; }); delayTime += stagger; } diff --git a/Example/UICatalog/AAPLCatalogTableTableViewController.m b/Example/UICatalog/AAPLCatalogTableTableViewController.m index 1fc8487927..052e3e927c 100644 --- a/Example/UICatalog/AAPLCatalogTableTableViewController.m +++ b/Example/UICatalog/AAPLCatalogTableTableViewController.m @@ -34,10 +34,10 @@ - (void)flexButtonTapped:(id)sender - (void)registerViewControllerBasedOption { // create UIViewController subclass - UIViewController *viewController = [[UIViewController alloc] init]; + UIViewController *viewController = [UIViewController new]; // fill it with some stuff - UILabel *infoLabel = [[UILabel alloc] init]; + UILabel *infoLabel = [UILabel new]; infoLabel.translatesAutoresizingMaskIntoConstraints = NO; infoLabel.text = @"Add switches, notes or whatever you wish to provide your testers with superpowers!"; infoLabel.numberOfLines = 0; diff --git a/Example/UICatalog/AAPLDatePickerController.m b/Example/UICatalog/AAPLDatePickerController.m index e7507ef807..e0b4920d4e 100644 --- a/Example/UICatalog/AAPLDatePickerController.m +++ b/Example/UICatalog/AAPLDatePickerController.m @@ -65,7 +65,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // Create a date formatter to be used to format the "date" property of "datePicker". - self.dateFormatter = [[NSDateFormatter alloc] init]; + self.dateFormatter = [NSDateFormatter new]; self.dateFormatter.dateStyle = NSDateFormatterMediumStyle; self.dateFormatter.timeStyle = NSDateFormatterShortStyle; @@ -85,7 +85,7 @@ - (void)configureDatePicker { NSCalendar *currentCalendar = [NSCalendar currentCalendar]; - NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + NSDateComponents *dateComponents = [NSDateComponents new]; dateComponents.day = 7; NSDate *sevenDaysFromNow = [currentCalendar dateByAddingComponents:dateComponents toDate:now options:0]; diff --git a/Example/UICatalog/AAPLProgressViewController.m b/Example/UICatalog/AAPLProgressViewController.m index de948f8673..775618b6c4 100644 --- a/Example/UICatalog/AAPLProgressViewController.m +++ b/Example/UICatalog/AAPLProgressViewController.m @@ -118,7 +118,7 @@ - (void)configureTintedProgressView { - (void)simulateProgress { // In this example we will simulate progress with a "sleep operation". - self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue = [NSOperationQueue new]; for (NSUInteger count = 0; count < kProgressViewControllerMaxProgress; count++) { [self.operationQueue addOperationWithBlock:^{ diff --git a/Example/UICatalog/AAPLTextViewController.m b/Example/UICatalog/AAPLTextViewController.m index 2844d504f0..6817c1b963 100644 --- a/Example/UICatalog/AAPLTextViewController.m +++ b/Example/UICatalog/AAPLTextViewController.m @@ -167,7 +167,7 @@ - (void)configureTextView { [attributedText addAttribute:NSForegroundColorAttributeName value:UIColor.aapl_applicationBlueColor range:tintedRange]; // Add an image attachment. - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; + NSTextAttachment *textAttachment = [NSTextAttachment new]; UIImage *image = [UIImage imageNamed:@"text_view_attachment"]; textAttachment.image = image; textAttachment.bounds = CGRectMake(0, 0, image.size.width, image.size.height); From bff9f1dd898fd723cacad39cd8014d13758e29f6 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Fri, 16 Aug 2019 12:39:16 -0500 Subject: [PATCH 06/45] Remove redundant property attributes Object properties are strong by default, and primitive ones are assign by default. Verbosity is nice, but in this case it introduces unnecessary cognitive load. Remove all usage of `strong` and `assign` property attributes --- .../FLEXArgumentInputColorView.m | 20 ++++++------- .../FLEXArgumentInputDateView.m | 2 +- .../FLEXArgumentInputFontView.m | 4 +-- .../FLEXArgumentInputFontsPickerView.m | 2 +- .../FLEXArgumentInputStructView.m | 2 +- .../FLEXArgumentInputSwitchView.m | 2 +- .../FLEXArgumentInputView.h | 6 ++-- .../FLEXArgumentInputView.m | 4 +-- .../Editing/FLEXDefaultEditorViewController.m | 2 +- Classes/Editing/FLEXFieldEditorView.h | 2 +- Classes/Editing/FLEXFieldEditorView.m | 8 +++--- .../Editing/FLEXFieldEditorViewController.h | 6 ++-- .../Editing/FLEXFieldEditorViewController.m | 8 +++--- .../Editing/FLEXIvarEditorViewController.m | 2 +- .../Editing/FLEXMethodCallingViewController.m | 4 +-- .../FLEXMutableFieldEditorViewController.h | 2 +- .../FLEXMutableFieldEditorViewController.m | 2 +- .../FLEXPropertyEditorViewController.m | 2 +- .../FLEXExplorerViewController.m | 26 ++++++++--------- Classes/FLEXManager.h | 6 ++-- .../FLEXMultiColumnTableView.m | 16 +++++------ .../FLEXRealmDatabaseManager.m | 2 +- .../DatabaseBrowser/FLEXTableColumnHeader.h | 2 +- .../DatabaseBrowser/FLEXTableContentCell.h | 2 +- .../FLEXTableContentViewController.h | 4 +-- .../FLEXTableContentViewController.m | 2 +- .../DatabaseBrowser/FLEXTableLeftCell.h | 2 +- .../FLEXTableListViewController.m | 2 +- .../FLEXClassesTableViewController.m | 4 +-- .../FLEXCookiesTableViewController.m | 2 +- .../FLEXLibrariesTableViewController.m | 6 ++-- .../FLEXLiveObjectsTableViewController.m | 6 ++-- .../FLEXWebViewController.m | 4 +-- .../FLEXFileBrowserSearchOperation.m | 4 +-- .../FLEXFileBrowserTableViewController.m | 10 +++---- .../SystemLog/FLEXASLLogController.m | 2 +- .../SystemLog/FLEXSystemLogTableViewCell.h | 2 +- .../SystemLog/FLEXSystemLogTableViewCell.m | 4 +-- Classes/Manager/FLEXManager+Private.h | 4 +-- Classes/Manager/FLEXManager.m | 8 +++--- .../FLEXNetworkHistoryTableViewController.m | 8 +++--- Classes/Network/FLEXNetworkRecorder.h | 4 +-- Classes/Network/FLEXNetworkRecorder.m | 8 +++--- .../FLEXNetworkSettingsTableViewController.m | 2 +- Classes/Network/FLEXNetworkTransaction.h | 20 ++++++------- Classes/Network/FLEXNetworkTransaction.m | 2 +- ...workTransactionDetailTableViewController.h | 2 +- .../FLEXNetworkTransactionTableViewCell.h | 2 +- .../FLEXNetworkTransactionTableViewCell.m | 8 +++--- .../PonyDebugger/FLEXNetworkObserver.m | 6 ++-- .../FLEXObjectExplorerViewController.h | 2 +- .../FLEXObjectExplorerViewController.m | 28 +++++++++---------- Classes/Toolbar/FLEXExplorerToolbar.h | 16 +++++------ Classes/Toolbar/FLEXExplorerToolbar.m | 24 ++++++++-------- Classes/Toolbar/FLEXToolbarItem.m | 2 +- .../Utility/FLEXKeyboardHelpViewController.m | 2 +- Classes/Utility/FLEXKeyboardShortcutManager.h | 2 +- Classes/Utility/FLEXKeyboardShortcutManager.m | 20 ++++++------- .../FLEXHierarchyTableViewCell.h | 6 ++-- .../FLEXHierarchyTableViewCell.m | 4 +-- .../FLEXHierarchyTableViewController.m | 10 +++---- .../FLEXImagePreviewViewController.m | 6 ++-- Example/UICatalog/AAPLAppDelegate.h | 2 +- Example/UICatalog/AAPLAppDelegate.m | 4 +-- Example/UICatalog/AAPLDatePickerController.m | 2 +- .../UICatalog/AAPLPageControlViewController.m | 2 +- 66 files changed, 197 insertions(+), 197 deletions(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m index 654d719a78..61f604565a 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m @@ -14,8 +14,8 @@ @protocol FLEXColorComponentInputViewDelegate; @interface FLEXColorComponentInputView : UIView -@property (nonatomic, strong) UISlider *slider; -@property (nonatomic, strong) UILabel *valueLabel; +@property (nonatomic) UISlider *slider; +@property (nonatomic) UILabel *valueLabel; @property (nonatomic, weak) id delegate; @@ -94,9 +94,9 @@ - (CGSize)sizeThatFits:(CGSize)size @interface FLEXColorPreviewBox : UIView -@property (nonatomic, strong) UIColor *color; +@property (nonatomic) UIColor *color; -@property (nonatomic, strong) UIView *colorOverlayView; +@property (nonatomic) UIView *colorOverlayView; @end @@ -153,12 +153,12 @@ + (UIImage *)backgroundPatternImage @interface FLEXArgumentInputColorView () -@property (nonatomic, strong) FLEXColorPreviewBox *colorPreviewBox; -@property (nonatomic, strong) UILabel *hexLabel; -@property (nonatomic, strong) FLEXColorComponentInputView *alphaInput; -@property (nonatomic, strong) FLEXColorComponentInputView *redInput; -@property (nonatomic, strong) FLEXColorComponentInputView *greenInput; -@property (nonatomic, strong) FLEXColorComponentInputView *blueInput; +@property (nonatomic) FLEXColorPreviewBox *colorPreviewBox; +@property (nonatomic) UILabel *hexLabel; +@property (nonatomic) FLEXColorComponentInputView *alphaInput; +@property (nonatomic) FLEXColorComponentInputView *redInput; +@property (nonatomic) FLEXColorComponentInputView *greenInput; +@property (nonatomic) FLEXColorComponentInputView *blueInput; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m index 2efbab4be6..1447182518 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m @@ -11,7 +11,7 @@ @interface FLEXArgumentInputDateView () -@property (nonatomic, strong) UIDatePicker *datePicker; +@property (nonatomic) UIDatePicker *datePicker; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m index 803b76fa74..9e13aeaf20 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m @@ -13,8 +13,8 @@ @interface FLEXArgumentInputFontView () -@property (nonatomic, strong) FLEXArgumentInputView *fontNameInput; -@property (nonatomic, strong) FLEXArgumentInputView *pointSizeInput; +@property (nonatomic) FLEXArgumentInputView *fontNameInput; +@property (nonatomic) FLEXArgumentInputView *pointSizeInput; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m index 52d54e1700..1b4a3e1f56 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m @@ -11,7 +11,7 @@ @interface FLEXArgumentInputFontsPickerView () -@property (nonatomic, strong) NSMutableArray *availableFonts; +@property (nonatomic) NSMutableArray *availableFonts; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m index 897b1e11c2..aa35b606d0 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m @@ -12,7 +12,7 @@ @interface FLEXArgumentInputStructView () -@property (nonatomic, strong) NSArray *argumentInputViews; +@property (nonatomic) NSArray *argumentInputViews; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m index 48edfc4e99..fc12b908f4 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m @@ -10,7 +10,7 @@ @interface FLEXArgumentInputSwitchView () -@property (nonatomic, strong) UISwitch *inputSwitch; +@property (nonatomic) UISwitch *inputSwitch; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h index 48e9301fc0..677e509d45 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h @@ -32,7 +32,7 @@ typedef NS_ENUM(NSUInteger, FLEXArgumentInputViewSize) { /// Setting this value to large will make some argument input views increase the size of their input field(s). /// Useful to increase the use of space if there is only one input view on screen (i.e. for property and ivar editing). -@property (nonatomic, assign) FLEXArgumentInputViewSize targetSize; +@property (nonatomic) FLEXArgumentInputViewSize targetSize; /// Users of the input view can get delegate callbacks for incremental changes in user input. @property (nonatomic, weak) id delegate; @@ -48,8 +48,8 @@ typedef NS_ENUM(NSUInteger, FLEXArgumentInputViewSize) { // For subclass eyes only -@property (nonatomic, strong, readonly) UILabel *titleLabel; -@property (nonatomic, strong, readonly) NSString *typeEncoding; +@property (nonatomic, readonly) UILabel *titleLabel; +@property (nonatomic, readonly) NSString *typeEncoding; @property (nonatomic, readonly) CGFloat topInputFieldVerticalLayoutGuide; @end diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m index 22f7f9cf01..be3b1a50b4 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m @@ -11,8 +11,8 @@ @interface FLEXArgumentInputView () -@property (nonatomic, strong) UILabel *titleLabel; -@property (nonatomic, strong) NSString *typeEncoding; +@property (nonatomic) UILabel *titleLabel; +@property (nonatomic) NSString *typeEncoding; @end diff --git a/Classes/Editing/FLEXDefaultEditorViewController.m b/Classes/Editing/FLEXDefaultEditorViewController.m index 2839f14bb4..2e2deca600 100644 --- a/Classes/Editing/FLEXDefaultEditorViewController.m +++ b/Classes/Editing/FLEXDefaultEditorViewController.m @@ -15,7 +15,7 @@ @interface FLEXDefaultEditorViewController () @property (nonatomic, readonly) NSUserDefaults *defaults; -@property (nonatomic, strong) NSString *key; +@property (nonatomic) NSString *key; @end diff --git a/Classes/Editing/FLEXFieldEditorView.h b/Classes/Editing/FLEXFieldEditorView.h index f4159689b4..780d56410b 100644 --- a/Classes/Editing/FLEXFieldEditorView.h +++ b/Classes/Editing/FLEXFieldEditorView.h @@ -15,6 +15,6 @@ @property (nonatomic, copy) NSString *targetDescription; @property (nonatomic, copy) NSString *fieldDescription; -@property (nonatomic, strong) NSArray *argumentInputViews; +@property (nonatomic) NSArray *argumentInputViews; @end diff --git a/Classes/Editing/FLEXFieldEditorView.m b/Classes/Editing/FLEXFieldEditorView.m index 5fa9981f3d..c5898cd5e4 100644 --- a/Classes/Editing/FLEXFieldEditorView.m +++ b/Classes/Editing/FLEXFieldEditorView.m @@ -12,10 +12,10 @@ @interface FLEXFieldEditorView () -@property (nonatomic, strong) UILabel *targetDescriptionLabel; -@property (nonatomic, strong) UIView *targetDescriptionDivider; -@property (nonatomic, strong) UILabel *fieldDescriptionLabel; -@property (nonatomic, strong) UIView *fieldDescriptionDivider; +@property (nonatomic) UILabel *targetDescriptionLabel; +@property (nonatomic) UIView *targetDescriptionDivider; +@property (nonatomic) UILabel *fieldDescriptionLabel; +@property (nonatomic) UIView *fieldDescriptionDivider; @end diff --git a/Classes/Editing/FLEXFieldEditorViewController.h b/Classes/Editing/FLEXFieldEditorViewController.h index c8cc0a65f9..1b6afef833 100644 --- a/Classes/Editing/FLEXFieldEditorViewController.h +++ b/Classes/Editing/FLEXFieldEditorViewController.h @@ -19,9 +19,9 @@ @property (nonatomic, readonly) FLEXArgumentInputView *firstInputView; // For subclass use only. -@property (nonatomic, strong, readonly) id target; -@property (nonatomic, strong, readonly) FLEXFieldEditorView *fieldEditorView; -@property (nonatomic, strong, readonly) UIBarButtonItem *setterButton; +@property (nonatomic, readonly) id target; +@property (nonatomic, readonly) FLEXFieldEditorView *fieldEditorView; +@property (nonatomic, readonly) UIBarButtonItem *setterButton; - (void)actionButtonPressed:(id)sender; - (NSString *)titleForActionButton; diff --git a/Classes/Editing/FLEXFieldEditorViewController.m b/Classes/Editing/FLEXFieldEditorViewController.m index 69223f2640..4d8d93b63d 100644 --- a/Classes/Editing/FLEXFieldEditorViewController.m +++ b/Classes/Editing/FLEXFieldEditorViewController.m @@ -18,11 +18,11 @@ @interface FLEXFieldEditorViewController () -@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic) UIScrollView *scrollView; -@property (nonatomic, strong, readwrite) id target; -@property (nonatomic, strong, readwrite) FLEXFieldEditorView *fieldEditorView; -@property (nonatomic, strong, readwrite) UIBarButtonItem *setterButton; +@property (nonatomic, readwrite) id target; +@property (nonatomic, readwrite) FLEXFieldEditorView *fieldEditorView; +@property (nonatomic, readwrite) UIBarButtonItem *setterButton; @end diff --git a/Classes/Editing/FLEXIvarEditorViewController.m b/Classes/Editing/FLEXIvarEditorViewController.m index a9aab92b03..bddcaa821a 100644 --- a/Classes/Editing/FLEXIvarEditorViewController.m +++ b/Classes/Editing/FLEXIvarEditorViewController.m @@ -15,7 +15,7 @@ @interface FLEXIvarEditorViewController () -@property (nonatomic, assign) Ivar ivar; +@property (nonatomic) Ivar ivar; @end diff --git a/Classes/Editing/FLEXMethodCallingViewController.m b/Classes/Editing/FLEXMethodCallingViewController.m index 7663c4d5d9..6da66d2f61 100644 --- a/Classes/Editing/FLEXMethodCallingViewController.m +++ b/Classes/Editing/FLEXMethodCallingViewController.m @@ -16,8 +16,8 @@ @interface FLEXMethodCallingViewController () -@property (nonatomic, assign) Method method; -@property (nonatomic, assign) FLEXTypeEncoding *returnType; +@property (nonatomic) Method method; +@property (nonatomic) FLEXTypeEncoding *returnType; @end diff --git a/Classes/Editing/FLEXMutableFieldEditorViewController.h b/Classes/Editing/FLEXMutableFieldEditorViewController.h index b69d8eb612..6ea033c10a 100644 --- a/Classes/Editing/FLEXMutableFieldEditorViewController.h +++ b/Classes/Editing/FLEXMutableFieldEditorViewController.h @@ -10,7 +10,7 @@ @interface FLEXMutableFieldEditorViewController : FLEXFieldEditorViewController -@property (nonatomic, strong, readonly) UIBarButtonItem *getterButton; +@property (nonatomic, readonly) UIBarButtonItem *getterButton; - (void)getterButtonPressed:(id)sender; - (NSString *)titleForGetterButton; diff --git a/Classes/Editing/FLEXMutableFieldEditorViewController.m b/Classes/Editing/FLEXMutableFieldEditorViewController.m index 69c42f378b..65dcd61592 100644 --- a/Classes/Editing/FLEXMutableFieldEditorViewController.m +++ b/Classes/Editing/FLEXMutableFieldEditorViewController.m @@ -11,7 +11,7 @@ @interface FLEXMutableFieldEditorViewController () -@property (nonatomic, strong, readwrite) UIBarButtonItem *getterButton; +@property (nonatomic, readwrite) UIBarButtonItem *getterButton; @end diff --git a/Classes/Editing/FLEXPropertyEditorViewController.m b/Classes/Editing/FLEXPropertyEditorViewController.m index efa515ccb6..ce65377d86 100644 --- a/Classes/Editing/FLEXPropertyEditorViewController.m +++ b/Classes/Editing/FLEXPropertyEditorViewController.m @@ -15,7 +15,7 @@ @interface FLEXPropertyEditorViewController () -@property (nonatomic, assign) objc_property_t property; +@property (nonatomic) objc_property_t property; @end diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index b3d043a6af..50be3a17b9 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -26,49 +26,49 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) { @interface FLEXExplorerViewController () -@property (nonatomic, strong) FLEXExplorerToolbar *explorerToolbar; +@property (nonatomic) FLEXExplorerToolbar *explorerToolbar; /// Tracks the currently active tool/mode -@property (nonatomic, assign) FLEXExplorerMode currentMode; +@property (nonatomic) FLEXExplorerMode currentMode; /// Gesture recognizer for dragging a view in move mode -@property (nonatomic, strong) UIPanGestureRecognizer *movePanGR; +@property (nonatomic) UIPanGestureRecognizer *movePanGR; /// Gesture recognizer for showing additional details on the selected view -@property (nonatomic, strong) UITapGestureRecognizer *detailsTapGR; +@property (nonatomic) UITapGestureRecognizer *detailsTapGR; /// Only valid while a move pan gesture is in progress. -@property (nonatomic, assign) CGRect selectedViewFrameBeforeDragging; +@property (nonatomic) CGRect selectedViewFrameBeforeDragging; /// Only valid while a toolbar drag pan gesture is in progress. -@property (nonatomic, assign) CGRect toolbarFrameBeforeDragging; +@property (nonatomic) CGRect toolbarFrameBeforeDragging; /// Borders of all the visible views in the hierarchy at the selection point. /// The keys are NSValues with the corresponding view (nonretained). -@property (nonatomic, strong) NSDictionary *outlineViewsForVisibleViews; +@property (nonatomic) NSDictionary *outlineViewsForVisibleViews; /// The actual views at the selection point with the deepest view last. -@property (nonatomic, strong) NSArray *viewsAtTapPoint; +@property (nonatomic) NSArray *viewsAtTapPoint; /// The view that we're currently highlighting with an overlay and displaying details for. -@property (nonatomic, strong) UIView *selectedView; +@property (nonatomic) UIView *selectedView; /// A colored transparent overlay to indicate that the view is selected. -@property (nonatomic, strong) UIView *selectedViewOverlay; +@property (nonatomic) UIView *selectedViewOverlay; /// Tracked so we can restore the key window after dismissing a modal. /// We need to become key after modal presentation so we can correctly capture input. /// If we're just showing the toolbar, we want the main app's window to remain key so that we don't interfere with input, status bar, etc. -@property (nonatomic, strong) UIWindow *previousKeyWindow; +@property (nonatomic) UIWindow *previousKeyWindow; /// Similar to the previousKeyWindow property above, we need to track status bar styling if /// the app doesn't use view controller based status bar management. When we present a modal, /// we want to change the status bar style to UIStatusBarStyleDefault. Before changing, we stash /// the current style. On dismissal, we return the status bar to the style that the app was using previously. -@property (nonatomic, assign) UIStatusBarStyle previousStatusBarStyle; +@property (nonatomic) UIStatusBarStyle previousStatusBarStyle; /// All views that we're KVOing. Used to help us clean up properly. -@property (nonatomic, strong) NSMutableSet *observedViews; +@property (nonatomic) NSMutableSet *observedViews; @end diff --git a/Classes/FLEXManager.h b/Classes/FLEXManager.h index 7e4a00d1e7..6b5205692f 100644 --- a/Classes/FLEXManager.h +++ b/Classes/FLEXManager.h @@ -34,11 +34,11 @@ typedef UIViewController *(^FLEXCustomContentViewerFuture)(NSData *data); /// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods /// on classes that conform to the protocols. This allows you to view network activity history from the main FLEX menu. /// Full responses are kept temporarily in a size-limited cache and may be pruned under memory pressure. -@property (nonatomic, assign, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled; +@property (nonatomic, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled; /// Defaults to 25 MB if never set. Values set here are persisted across launches of the app. /// The response cache uses an NSCache, so it may purge prior to hitting the limit when the app is under memory pressure. -@property (nonatomic, assign) NSUInteger networkResponseCacheByteLimit; +@property (nonatomic) NSUInteger networkResponseCacheByteLimit; /// Requests whose host ends with one of the blacklisted entries in this array will be not be recorded (eg. google.com). /// Wildcard or subdomain entries are not required (eg. google.com will match any subdomain under google.com). @@ -52,7 +52,7 @@ typedef UIViewController *(^FLEXCustomContentViewerFuture)(NSData *data); /// The shortcuts will not fire when there is an active text field, text view, or other responder accepting key input. /// You can disable keyboard shortcuts if you have existing keyboard shortcuts that conflict with FLEX, or if you like doing things the hard way ;) /// Keyboard shortcuts are always disabled (and support is compiled out) in non-simulator builds -@property (nonatomic, assign) BOOL simulatorShortcutsEnabled; +@property (nonatomic) BOOL simulatorShortcutsEnabled; /// Adds an action to run when the specified key & modifier combination is pressed /// @param key A single character string matching a key on the keyboard diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m index 28b2d4957a..2390256725 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m @@ -13,14 +13,14 @@ @interface FLEXMultiColumnTableView () -@property (nonatomic, strong) UIScrollView *contentScrollView; -@property (nonatomic, strong) UIScrollView *headerScrollView; -@property (nonatomic, strong) UITableView *leftTableView; -@property (nonatomic, strong) UITableView *contentTableView; -@property (nonatomic, strong) UIView *leftHeader; - -@property (nonatomic, strong) NSDictionary *sortStatusDict; -@property (nonatomic, strong) NSArray *rowData; +@property (nonatomic) UIScrollView *contentScrollView; +@property (nonatomic) UIScrollView *headerScrollView; +@property (nonatomic) UITableView *leftTableView; +@property (nonatomic) UITableView *contentTableView; +@property (nonatomic) UIView *leftHeader; + +@property (nonatomic) NSDictionary *sortStatusDict; +@property (nonatomic) NSArray *rowData; @end static const CGFloat kColumnMargin = 1; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m index 605002ee47..b7800d9075 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m @@ -18,7 +18,7 @@ @interface FLEXRealmDatabaseManager () @property (nonatomic, copy) NSString *path; -@property (nonatomic, strong) RLMRealm * realm; +@property (nonatomic) RLMRealm * realm; @end diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h index 4f85de4916..05c2cf24cc 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h @@ -16,7 +16,7 @@ typedef NS_ENUM(NSUInteger, FLEXTableColumnHeaderSortType) { @interface FLEXTableColumnHeader : UIView -@property (nonatomic, strong) UILabel *label; +@property (nonatomic) UILabel *label; - (void)changeSortStatusWithType:(FLEXTableColumnHeaderSortType)type; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.h b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.h index 4f6273cfb6..123f3287e3 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.h +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentCell.h @@ -18,7 +18,7 @@ @interface FLEXTableContentCell : UITableViewCell -@property (nonatomic, strong) NSArray *labels; +@property (nonatomic) NSArray *labels; @property (nonatomic, weak) id delegate; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h index db985739d8..368b010848 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h @@ -10,7 +10,7 @@ @interface FLEXTableContentViewController : UIViewController -@property (nonatomic, strong) NSArray *columnsArray; -@property (nonatomic, strong) NSArray *> *contentsArray; +@property (nonatomic) NSArray *columnsArray; +@property (nonatomic) NSArray *> *contentsArray; @end diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m index 92c0abdd54..29b0353d45 100755 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m @@ -13,7 +13,7 @@ @interface FLEXTableContentViewController () -@property (nonatomic, strong) FLEXMultiColumnTableView *multiColumnView; +@property (nonatomic) FLEXMultiColumnTableView *multiColumnView; @end diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h index 0c6c09af9e..e3510729c6 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h @@ -10,7 +10,7 @@ @interface FLEXTableLeftCell : UITableViewCell -@property (nonatomic, strong) UILabel *titlelabel; +@property (nonatomic) UILabel *titlelabel; + (instancetype)cellWithTableView:(UITableView *)tableView; diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m index 5d7a1969a4..bef7eb273f 100644 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m @@ -20,7 +20,7 @@ @interface FLEXTableListViewController () NSString *_databasePath; } -@property (nonatomic, strong) NSArray *tables; +@property (nonatomic) NSArray *tables; + (NSArray *)supportedSQLiteExtensions; + (NSArray *)supportedRealmExtensions; diff --git a/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m b/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m index b1a44acc3f..7ed7c9e473 100644 --- a/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXClassesTableViewController.m @@ -14,8 +14,8 @@ @interface FLEXClassesTableViewController () -@property (nonatomic, strong) NSArray *classNames; -@property (nonatomic, strong) NSArray *filteredClassNames; +@property (nonatomic) NSArray *classNames; +@property (nonatomic) NSArray *filteredClassNames; @end diff --git a/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m b/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m index 2a01bd5789..0c66bbc38d 100644 --- a/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXCookiesTableViewController.m @@ -12,7 +12,7 @@ @interface FLEXCookiesTableViewController () -@property (nonatomic, strong) NSArray *cookies; +@property (nonatomic) NSArray *cookies; @end diff --git a/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m b/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m index 6f3d9926dc..22810612f4 100644 --- a/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXLibrariesTableViewController.m @@ -14,10 +14,10 @@ @interface FLEXLibrariesTableViewController () -@property (nonatomic, strong) NSArray *imageNames; -@property (nonatomic, strong) NSArray *filteredImageNames; +@property (nonatomic) NSArray *imageNames; +@property (nonatomic) NSArray *filteredImageNames; -@property (nonatomic, strong) Class foundClass; +@property (nonatomic) Class foundClass; @end diff --git a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m index f1586bd796..5224ef636b 100644 --- a/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXLiveObjectsTableViewController.m @@ -19,10 +19,10 @@ @interface FLEXLiveObjectsTableViewController () -@property (nonatomic, strong) NSDictionary *instanceCountsForClassNames; -@property (nonatomic, strong) NSDictionary *instanceSizesForClassNames; +@property (nonatomic) NSDictionary *instanceCountsForClassNames; +@property (nonatomic) NSDictionary *instanceSizesForClassNames; @property (nonatomic, readonly) NSArray *allClassNames; -@property (nonatomic, strong) NSArray *filteredClassNames; +@property (nonatomic) NSArray *filteredClassNames; @end diff --git a/Classes/GlobalStateExplorers/FLEXWebViewController.m b/Classes/GlobalStateExplorers/FLEXWebViewController.m index 2080430eac..7887053e61 100644 --- a/Classes/GlobalStateExplorers/FLEXWebViewController.m +++ b/Classes/GlobalStateExplorers/FLEXWebViewController.m @@ -12,8 +12,8 @@ @interface FLEXWebViewController () -@property (nonatomic, strong) WKWebView *webView; -@property (nonatomic, strong) NSString *originalText; +@property (nonatomic) WKWebView *webView; +@property (nonatomic) NSString *originalText; @end diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m index 0ac57271c8..8666ba3d49 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m @@ -26,8 +26,8 @@ - (id)flex_pop @interface FLEXFileBrowserSearchOperation () -@property (nonatomic, strong) NSString *path; -@property (nonatomic, strong) NSString *searchString; +@property (nonatomic) NSString *path; +@property (nonatomic) NSString *searchString; @end diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index b01b8e49de..59c32b9c20 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -22,12 +22,12 @@ @interface FLEXFileBrowserTableViewController () *childPaths; -@property (nonatomic, strong) NSArray *searchPaths; -@property (nonatomic, strong) NSNumber *recursiveSize; -@property (nonatomic, strong) NSNumber *searchPathsSize; +@property (nonatomic) NSArray *searchPaths; +@property (nonatomic) NSNumber *recursiveSize; +@property (nonatomic) NSNumber *searchPathsSize; @property (nonatomic) NSOperationQueue *operationQueue; -@property (nonatomic, strong) UIDocumentInteractionController *documentController; -@property (nonatomic, strong) id fileOperationController; +@property (nonatomic) UIDocumentInteractionController *documentController; +@property (nonatomic) id fileOperationController; @end diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m index 07a3cbd587..ff9f1bdf97 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXASLLogController.m @@ -20,7 +20,7 @@ @interface FLEXASLLogController () @property (nonatomic, readonly) void (^updateHandler)(NSArray *); -@property (nonatomic, strong) NSTimer *logUpdateTimer; +@property (nonatomic) NSTimer *logUpdateTimer; @property (nonatomic, readonly) NSMutableIndexSet *logMessageIdentifiers; // ASL stuff diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.h b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.h index d35d5c53b6..c1da32e6d8 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.h +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.h @@ -14,7 +14,7 @@ extern NSString *const kFLEXSystemLogTableViewCellIdentifier; @interface FLEXSystemLogTableViewCell : UITableViewCell -@property (nonatomic, strong) FLEXSystemLogMessage *logMessage; +@property (nonatomic) FLEXSystemLogMessage *logMessage; @property (nonatomic, copy) NSString *highlightedText; + (NSString *)displayedTextForLogMessage:(FLEXSystemLogMessage *)logMessage; diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m index 6516232343..b17af68baa 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewCell.m @@ -13,8 +13,8 @@ @interface FLEXSystemLogTableViewCell () -@property (nonatomic, strong) UILabel *logMessageLabel; -@property (nonatomic, strong) NSAttributedString *logMessageAttributedText; +@property (nonatomic) UILabel *logMessageLabel; +@property (nonatomic) NSAttributedString *logMessageAttributedText; @end diff --git a/Classes/Manager/FLEXManager+Private.h b/Classes/Manager/FLEXManager+Private.h index ea1e2bce83..5f79deec9f 100644 --- a/Classes/Manager/FLEXManager+Private.h +++ b/Classes/Manager/FLEXManager+Private.h @@ -13,8 +13,8 @@ @interface FLEXManager () /// An array of FLEXGlobalsEntry objects that have been registered by the user. -@property (nonatomic, readonly, strong) NSArray *userGlobalEntries; +@property (nonatomic, readonly) NSArray *userGlobalEntries; -@property (nonatomic, readonly, strong) NSDictionary *customContentTypeViewers; +@property (nonatomic, readonly) NSDictionary *customContentTypeViewers; @end diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 259c359874..9d50190817 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -22,11 +22,11 @@ @interface FLEXManager () -@property (nonatomic, strong) FLEXWindow *explorerWindow; -@property (nonatomic, strong) FLEXExplorerViewController *explorerViewController; +@property (nonatomic) FLEXWindow *explorerWindow; +@property (nonatomic) FLEXExplorerViewController *explorerViewController; -@property (nonatomic, readonly, strong) NSMutableArray *userGlobalEntries; -@property (nonatomic, readonly, strong) NSMutableDictionary *customContentTypeViewers; +@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; +@property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; @end diff --git a/Classes/Network/FLEXNetworkHistoryTableViewController.m b/Classes/Network/FLEXNetworkHistoryTableViewController.m index 2a85ac8e70..9607f737a5 100644 --- a/Classes/Network/FLEXNetworkHistoryTableViewController.m +++ b/Classes/Network/FLEXNetworkHistoryTableViewController.m @@ -19,12 +19,12 @@ @interface FLEXNetworkHistoryTableViewController () /// Backing model @property (nonatomic, copy) NSArray *networkTransactions; -@property (nonatomic, assign) long long bytesReceived; +@property (nonatomic) long long bytesReceived; @property (nonatomic, copy) NSArray *filteredNetworkTransactions; -@property (nonatomic, assign) long long filteredBytesReceived; +@property (nonatomic) long long filteredBytesReceived; -@property (nonatomic, assign) BOOL rowInsertInProgress; -@property (nonatomic, assign) BOOL isPresentingSearch; +@property (nonatomic) BOOL rowInsertInProgress; +@property (nonatomic) BOOL isPresentingSearch; @end diff --git a/Classes/Network/FLEXNetworkRecorder.h b/Classes/Network/FLEXNetworkRecorder.h index 292dc9f5c0..803384f4f5 100644 --- a/Classes/Network/FLEXNetworkRecorder.h +++ b/Classes/Network/FLEXNetworkRecorder.h @@ -22,10 +22,10 @@ extern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification; + (instancetype)defaultRecorder; /// Defaults to 25 MB if never set. Values set here are persisted across launches of the app. -@property (nonatomic, assign) NSUInteger responseCacheByteLimit; +@property (nonatomic) NSUInteger responseCacheByteLimit; /// If NO, the recorder not cache will not cache response for content types with an "image", "video", or "audio" prefix. -@property (nonatomic, assign) BOOL shouldCacheMediaResponses; +@property (nonatomic) BOOL shouldCacheMediaResponses; @property (nonatomic, copy) NSArray *hostBlacklist; diff --git a/Classes/Network/FLEXNetworkRecorder.m b/Classes/Network/FLEXNetworkRecorder.m index b685286c22..52335849c1 100644 --- a/Classes/Network/FLEXNetworkRecorder.m +++ b/Classes/Network/FLEXNetworkRecorder.m @@ -21,10 +21,10 @@ @interface FLEXNetworkRecorder () -@property (nonatomic, strong) NSCache *responseCache; -@property (nonatomic, strong) NSMutableArray *orderedTransactions; -@property (nonatomic, strong) NSMutableDictionary *networkTransactionsForRequestIdentifiers; -@property (nonatomic, strong) dispatch_queue_t queue; +@property (nonatomic) NSCache *responseCache; +@property (nonatomic) NSMutableArray *orderedTransactions; +@property (nonatomic) NSMutableDictionary *networkTransactionsForRequestIdentifiers; +@property (nonatomic) dispatch_queue_t queue; @end diff --git a/Classes/Network/FLEXNetworkSettingsTableViewController.m b/Classes/Network/FLEXNetworkSettingsTableViewController.m index 6c92f35b4e..f1a6f6552c 100644 --- a/Classes/Network/FLEXNetworkSettingsTableViewController.m +++ b/Classes/Network/FLEXNetworkSettingsTableViewController.m @@ -15,7 +15,7 @@ @interface FLEXNetworkSettingsTableViewController () @property (nonatomic, copy) NSArray *cells; -@property (nonatomic, strong) UITableViewCell *cacheLimitCell; +@property (nonatomic) UITableViewCell *cacheLimitCell; @end diff --git a/Classes/Network/FLEXNetworkTransaction.h b/Classes/Network/FLEXNetworkTransaction.h index 8c9d000067..f612438782 100644 --- a/Classes/Network/FLEXNetworkTransaction.h +++ b/Classes/Network/FLEXNetworkTransaction.h @@ -21,23 +21,23 @@ typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) { @property (nonatomic, copy) NSString *requestID; -@property (nonatomic, strong) NSURLRequest *request; -@property (nonatomic, strong) NSURLResponse *response; +@property (nonatomic) NSURLRequest *request; +@property (nonatomic) NSURLResponse *response; @property (nonatomic, copy) NSString *requestMechanism; -@property (nonatomic, assign) FLEXNetworkTransactionState transactionState; -@property (nonatomic, strong) NSError *error; +@property (nonatomic) FLEXNetworkTransactionState transactionState; +@property (nonatomic) NSError *error; -@property (nonatomic, strong) NSDate *startTime; -@property (nonatomic, assign) NSTimeInterval latency; -@property (nonatomic, assign) NSTimeInterval duration; +@property (nonatomic) NSDate *startTime; +@property (nonatomic) NSTimeInterval latency; +@property (nonatomic) NSTimeInterval duration; -@property (nonatomic, assign) int64_t receivedDataLength; +@property (nonatomic) int64_t receivedDataLength; /// Only applicable for image downloads. A small thumbnail to preview the full response. -@property (nonatomic, strong) UIImage *responseThumbnail; +@property (nonatomic) UIImage *responseThumbnail; /// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams. -@property (nonatomic, strong, readonly) NSData *cachedRequestBody; +@property (nonatomic, readonly) NSData *cachedRequestBody; + (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state; diff --git a/Classes/Network/FLEXNetworkTransaction.m b/Classes/Network/FLEXNetworkTransaction.m index 87a9892497..5ada330c68 100644 --- a/Classes/Network/FLEXNetworkTransaction.m +++ b/Classes/Network/FLEXNetworkTransaction.m @@ -10,7 +10,7 @@ @interface FLEXNetworkTransaction () -@property (nonatomic, strong, readwrite) NSData *cachedRequestBody; +@property (nonatomic, readwrite) NSData *cachedRequestBody; @end diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.h b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.h index 2e065faf8b..a8df555c18 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.h +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.h @@ -12,6 +12,6 @@ @interface FLEXNetworkTransactionDetailTableViewController : UITableViewController -@property (nonatomic, strong) FLEXNetworkTransaction *transaction; +@property (nonatomic) FLEXNetworkTransaction *transaction; @end diff --git a/Classes/Network/FLEXNetworkTransactionTableViewCell.h b/Classes/Network/FLEXNetworkTransactionTableViewCell.h index 385573da95..6501c3c9e8 100644 --- a/Classes/Network/FLEXNetworkTransactionTableViewCell.h +++ b/Classes/Network/FLEXNetworkTransactionTableViewCell.h @@ -14,7 +14,7 @@ extern NSString *const kFLEXNetworkTransactionCellIdentifier; @interface FLEXNetworkTransactionTableViewCell : UITableViewCell -@property (nonatomic, strong) FLEXNetworkTransaction *transaction; +@property (nonatomic) FLEXNetworkTransaction *transaction; + (CGFloat)preferredCellHeight; diff --git a/Classes/Network/FLEXNetworkTransactionTableViewCell.m b/Classes/Network/FLEXNetworkTransactionTableViewCell.m index cdbfe3a2e9..e89a1fe8c7 100644 --- a/Classes/Network/FLEXNetworkTransactionTableViewCell.m +++ b/Classes/Network/FLEXNetworkTransactionTableViewCell.m @@ -16,10 +16,10 @@ @interface FLEXNetworkTransactionTableViewCell () -@property (nonatomic, strong) UIImageView *thumbnailImageView; -@property (nonatomic, strong) UILabel *nameLabel; -@property (nonatomic, strong) UILabel *pathLabel; -@property (nonatomic, strong) UILabel *transactionDetailsLabel; +@property (nonatomic) UIImageView *thumbnailImageView; +@property (nonatomic) UILabel *nameLabel; +@property (nonatomic) UILabel *pathLabel; +@property (nonatomic) UILabel *transactionDetailsLabel; @end diff --git a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m index b157428c48..34909571da 100644 --- a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m +++ b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m @@ -28,7 +28,7 @@ @interface FLEXInternalRequestState : NSObject @property (nonatomic, copy) NSURLRequest *request; -@property (nonatomic, strong) NSMutableData *dataAccumulator; +@property (nonatomic) NSMutableData *dataAccumulator; @end @@ -68,8 +68,8 @@ - (void)URLSessionTaskWillResume:(NSURLSessionTask *)task; @interface FLEXNetworkObserver () -@property (nonatomic, strong) NSMutableDictionary *requestStatesForRequestIDs; -@property (nonatomic, strong) dispatch_queue_t queue; +@property (nonatomic) NSMutableDictionary *requestStatesForRequestIDs; +@property (nonatomic) dispatch_queue_t queue; @end diff --git a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.h b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.h index 2990f3f912..ad2baef15c 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.h +++ b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.h @@ -21,7 +21,7 @@ typedef NS_ENUM(NSUInteger, FLEXObjectExplorerSection) { @interface FLEXObjectExplorerViewController : FLEXTableViewController -@property (nonatomic, strong) id object; +@property (nonatomic) id object; // Subclasses can override the methods below to provide data in a custom section. // The subclass should provide an array of "row cookies" to allow retrieval of individual row data later on. diff --git a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m index 83906365e3..c9041e2483 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m @@ -28,44 +28,44 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) { // Convenience boxes to keep runtime properties, ivars, and methods in foundation collections. @interface FLEXPropertyBox : NSObject -@property (nonatomic, assign) objc_property_t property; +@property (nonatomic) objc_property_t property; @end @implementation FLEXPropertyBox @end @interface FLEXIvarBox : NSObject -@property (nonatomic, assign) Ivar ivar; +@property (nonatomic) Ivar ivar; @end @implementation FLEXIvarBox @end @interface FLEXMethodBox : NSObject -@property (nonatomic, assign) Method method; +@property (nonatomic) Method method; @end @implementation FLEXMethodBox @end @interface FLEXObjectExplorerViewController () -@property (nonatomic, strong) NSMutableArray *> *properties; -@property (nonatomic, strong) NSArray *filteredProperties; +@property (nonatomic) NSMutableArray *> *properties; +@property (nonatomic) NSArray *filteredProperties; -@property (nonatomic, strong) NSMutableArray *> *ivars; -@property (nonatomic, strong) NSArray *filteredIvars; +@property (nonatomic) NSMutableArray *> *ivars; +@property (nonatomic) NSArray *filteredIvars; -@property (nonatomic, strong) NSMutableArray *> *methods; -@property (nonatomic, strong) NSArray *filteredMethods; +@property (nonatomic) NSMutableArray *> *methods; +@property (nonatomic) NSArray *filteredMethods; -@property (nonatomic, strong) NSMutableArray *> *classMethods; -@property (nonatomic, strong) NSArray *filteredClassMethods; +@property (nonatomic) NSMutableArray *> *classMethods; +@property (nonatomic) NSArray *filteredClassMethods; @property (nonatomic, copy) NSArray *classHierarchy; @property (nonatomic, copy) NSArray *filteredSuperclasses; -@property (nonatomic, strong) NSArray *cachedCustomSectionRowCookies; -@property (nonatomic, strong) NSIndexSet *customSectionVisibleIndexes; +@property (nonatomic) NSArray *cachedCustomSectionRowCookies; +@property (nonatomic) NSIndexSet *customSectionVisibleIndexes; -@property (nonatomic, strong) NSString *filterText; +@property (nonatomic) NSString *filterText; /// An index into the `classHierarchy` array @property (nonatomic) NSInteger classScope; diff --git a/Classes/Toolbar/FLEXExplorerToolbar.h b/Classes/Toolbar/FLEXExplorerToolbar.h index b020e45a93..57eb96aa2c 100644 --- a/Classes/Toolbar/FLEXExplorerToolbar.h +++ b/Classes/Toolbar/FLEXExplorerToolbar.h @@ -18,36 +18,36 @@ /// Toolbar item for selecting views. /// Users of the toolbar can configure the enabled/selected state and event targets/actions. -@property (nonatomic, strong, readonly) FLEXToolbarItem *selectItem; +@property (nonatomic, readonly) FLEXToolbarItem *selectItem; /// Toolbar item for presenting a list with the view hierarchy. /// Users of the toolbar can configure the enabled state and event targets/actions. -@property (nonatomic, strong, readonly) FLEXToolbarItem *hierarchyItem; +@property (nonatomic, readonly) FLEXToolbarItem *hierarchyItem; /// Toolbar item for moving views. /// Users of the toolbar can configure the enabled/selected state and event targets/actions. -@property (nonatomic, strong, readonly) FLEXToolbarItem *moveItem; +@property (nonatomic, readonly) FLEXToolbarItem *moveItem; /// Toolbar item for inspecting details of the selected view. /// Users of the toolbar can configure the enabled state and event targets/actions. -@property (nonatomic, strong, readonly) FLEXToolbarItem *globalsItem; +@property (nonatomic, readonly) FLEXToolbarItem *globalsItem; /// Toolbar item for hiding the explorer. /// Users of the toolbar can configure the event targets/actions. -@property (nonatomic, strong, readonly) FLEXToolbarItem *closeItem; +@property (nonatomic, readonly) FLEXToolbarItem *closeItem; /// A view for moving the entire toolbar. /// Users of the toolbar can attach a pan gesture recognizer to decide how to reposition the toolbar. -@property (nonatomic, strong, readonly) UIView *dragHandle; +@property (nonatomic, readonly) UIView *dragHandle; /// A color matching the overlay on color on the selected view. -@property (nonatomic, strong) UIColor *selectedViewOverlayColor; +@property (nonatomic) UIColor *selectedViewOverlayColor; /// Description text for the selected view displayed below the toolbar items. @property (nonatomic, copy) NSString *selectedViewDescription; /// Area where details of the selected view are shown /// Users of the toolbar can attach a tap gesture recognizer to show additional details. -@property (nonatomic, strong, readonly) UIView *selectedViewDescriptionContainer; +@property (nonatomic, readonly) UIView *selectedViewDescriptionContainer; @end diff --git a/Classes/Toolbar/FLEXExplorerToolbar.m b/Classes/Toolbar/FLEXExplorerToolbar.m index e77a9a1ca7..d1d3a3865d 100644 --- a/Classes/Toolbar/FLEXExplorerToolbar.m +++ b/Classes/Toolbar/FLEXExplorerToolbar.m @@ -14,21 +14,21 @@ @interface FLEXExplorerToolbar () -@property (nonatomic, strong, readwrite) FLEXToolbarItem *selectItem; -@property (nonatomic, strong, readwrite) FLEXToolbarItem *moveItem; -@property (nonatomic, strong, readwrite) FLEXToolbarItem *globalsItem; -@property (nonatomic, strong, readwrite) FLEXToolbarItem *closeItem; -@property (nonatomic, strong, readwrite) FLEXToolbarItem *hierarchyItem; -@property (nonatomic, strong, readwrite) UIView *dragHandle; +@property (nonatomic, readwrite) FLEXToolbarItem *selectItem; +@property (nonatomic, readwrite) FLEXToolbarItem *moveItem; +@property (nonatomic, readwrite) FLEXToolbarItem *globalsItem; +@property (nonatomic, readwrite) FLEXToolbarItem *closeItem; +@property (nonatomic, readwrite) FLEXToolbarItem *hierarchyItem; +@property (nonatomic, readwrite) UIView *dragHandle; -@property (nonatomic, strong) UIImageView *dragHandleImageView; +@property (nonatomic) UIImageView *dragHandleImageView; -@property (nonatomic, strong) UIView *selectedViewDescriptionContainer; -@property (nonatomic, strong) UIView *selectedViewDescriptionSafeAreaContainer; -@property (nonatomic, strong) UIView *selectedViewColorIndicator; -@property (nonatomic, strong) UILabel *selectedViewDescriptionLabel; +@property (nonatomic) UIView *selectedViewDescriptionContainer; +@property (nonatomic) UIView *selectedViewDescriptionSafeAreaContainer; +@property (nonatomic) UIView *selectedViewColorIndicator; +@property (nonatomic) UILabel *selectedViewDescriptionLabel; -@property (nonatomic, strong,readwrite) UIView *backgroundView; +@property (nonatomic,readwrite) UIView *backgroundView; @end diff --git a/Classes/Toolbar/FLEXToolbarItem.m b/Classes/Toolbar/FLEXToolbarItem.m index 40af50682e..cfe4abe421 100644 --- a/Classes/Toolbar/FLEXToolbarItem.m +++ b/Classes/Toolbar/FLEXToolbarItem.m @@ -13,7 +13,7 @@ @interface FLEXToolbarItem () @property (nonatomic, copy) NSString *title; -@property (nonatomic, strong) UIImage *image; +@property (nonatomic) UIImage *image; @end diff --git a/Classes/Utility/FLEXKeyboardHelpViewController.m b/Classes/Utility/FLEXKeyboardHelpViewController.m index 1dd5a91f7c..1bc41233d2 100644 --- a/Classes/Utility/FLEXKeyboardHelpViewController.m +++ b/Classes/Utility/FLEXKeyboardHelpViewController.m @@ -11,7 +11,7 @@ @interface FLEXKeyboardHelpViewController () -@property (nonatomic, strong) UITextView *textView; +@property (nonatomic) UITextView *textView; @end diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.h b/Classes/Utility/FLEXKeyboardShortcutManager.h index 732a8cbf5b..84a4468566 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.h +++ b/Classes/Utility/FLEXKeyboardShortcutManager.h @@ -17,7 +17,7 @@ - (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description; - (NSString *)keyboardShortcutsDescription; -@property (nonatomic, assign, getter=isEnabled) BOOL enabled; +@property (nonatomic, getter=isEnabled) BOOL enabled; @end diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.m b/Classes/Utility/FLEXKeyboardShortcutManager.m index 744bbfa81a..08c66e5499 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.m +++ b/Classes/Utility/FLEXKeyboardShortcutManager.m @@ -15,18 +15,18 @@ @interface UIEvent (UIPhysicalKeyboardEvent) -@property (nonatomic, strong) NSString *_modifiedInput; -@property (nonatomic, strong) NSString *_unmodifiedInput; -@property (nonatomic, assign) UIKeyModifierFlags _modifierFlags; -@property (nonatomic, assign) BOOL _isKeyDown; -@property (nonatomic, assign) long _keyCode; +@property (nonatomic) NSString *_modifiedInput; +@property (nonatomic) NSString *_unmodifiedInput; +@property (nonatomic) UIKeyModifierFlags _modifierFlags; +@property (nonatomic) BOOL _isKeyDown; +@property (nonatomic) long _keyCode; @end @interface FLEXKeyInput : NSObject @property (nonatomic, copy, readonly) NSString *key; -@property (nonatomic, assign, readonly) UIKeyModifierFlags flags; +@property (nonatomic, readonly) UIKeyModifierFlags flags; @property (nonatomic, copy, readonly) NSString *helpDescription; @end @@ -113,11 +113,11 @@ + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags h @interface FLEXKeyboardShortcutManager () -@property (nonatomic, strong) NSMutableDictionary *actionsForKeyInputs; +@property (nonatomic) NSMutableDictionary *actionsForKeyInputs; -@property (nonatomic, assign, getter=isPressingShift) BOOL pressingShift; -@property (nonatomic, assign, getter=isPressingCommand) BOOL pressingCommand; -@property (nonatomic, assign, getter=isPressingControl) BOOL pressingControl; +@property (nonatomic, getter=isPressingShift) BOOL pressingShift; +@property (nonatomic, getter=isPressingCommand) BOOL pressingCommand; +@property (nonatomic, getter=isPressingControl) BOOL pressingControl; @end diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.h b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.h index 6cc192f55e..b085ffc24a 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.h +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.h @@ -12,8 +12,8 @@ - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier; -@property (nonatomic, assign) NSInteger viewDepth; -@property (nonatomic, strong) UIColor *viewColor; -@property (nonatomic, strong) UIView *viewBackgroundColorView; +@property (nonatomic) NSInteger viewDepth; +@property (nonatomic) UIColor *viewColor; +@property (nonatomic) UIView *viewBackgroundColorView; @end diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m index 7ac85fec33..2c33279548 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewCell.m @@ -11,8 +11,8 @@ @interface FLEXHierarchyTableViewCell () -@property (nonatomic, strong) UIView *depthIndicatorView; -@property (nonatomic, strong) UIImageView *colorCircleImageView; +@property (nonatomic) UIView *depthIndicatorView; +@property (nonatomic) UIImageView *colorCircleImageView; @end diff --git a/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m b/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m index 94e9e18042..481e5161a6 100644 --- a/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m +++ b/Classes/ViewHierarchy/FLEXHierarchyTableViewController.m @@ -19,11 +19,11 @@ @interface FLEXHierarchyTableViewController () -@property (nonatomic, strong) NSArray *allViews; -@property (nonatomic, strong) NSDictionary *depthsForViews; -@property (nonatomic, strong) NSArray *viewsAtTap; -@property (nonatomic, strong) UIView *selectedView; -@property (nonatomic, strong) NSArray *displayedViews; +@property (nonatomic) NSArray *allViews; +@property (nonatomic) NSDictionary *depthsForViews; +@property (nonatomic) NSArray *viewsAtTap; +@property (nonatomic) UIView *selectedView; +@property (nonatomic) NSArray *displayedViews; @end diff --git a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m index 2ec5babb3f..4c88d37965 100644 --- a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m +++ b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m @@ -12,10 +12,10 @@ @interface FLEXImagePreviewViewController () -@property (nonatomic, strong) UIImage *image; +@property (nonatomic) UIImage *image; -@property (nonatomic, strong) UIScrollView *scrollView; -@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic) UIScrollView *scrollView; +@property (nonatomic) UIImageView *imageView; @end diff --git a/Example/UICatalog/AAPLAppDelegate.h b/Example/UICatalog/AAPLAppDelegate.h index 373f7e2f43..406a69045f 100644 --- a/Example/UICatalog/AAPLAppDelegate.h +++ b/Example/UICatalog/AAPLAppDelegate.h @@ -49,6 +49,6 @@ @interface AAPLAppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; +@property (nonatomic) UIWindow *window; @end diff --git a/Example/UICatalog/AAPLAppDelegate.m b/Example/UICatalog/AAPLAppDelegate.m index b3f6fb38fb..994b9ceb5c 100644 --- a/Example/UICatalog/AAPLAppDelegate.m +++ b/Example/UICatalog/AAPLAppDelegate.m @@ -58,8 +58,8 @@ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF @interface AAPLAppDelegate () -@property (nonatomic, strong) NSTimer *repeatingLogExampleTimer; -@property (nonatomic, strong) NSMutableArray *connections; +@property (nonatomic) NSTimer *repeatingLogExampleTimer; +@property (nonatomic) NSMutableArray *connections; @end diff --git a/Example/UICatalog/AAPLDatePickerController.m b/Example/UICatalog/AAPLDatePickerController.m index e0b4920d4e..5998e491fe 100644 --- a/Example/UICatalog/AAPLDatePickerController.m +++ b/Example/UICatalog/AAPLDatePickerController.m @@ -52,7 +52,7 @@ @interface AAPLDatePickerController() @property (nonatomic, weak) IBOutlet UIDatePicker *datePicker; @property (nonatomic, weak) IBOutlet UILabel *dateLabel; -@property (nonatomic, strong) NSDateFormatter *dateFormatter; +@property (nonatomic) NSDateFormatter *dateFormatter; @end diff --git a/Example/UICatalog/AAPLPageControlViewController.m b/Example/UICatalog/AAPLPageControlViewController.m index 6f67df6e98..20cbbcf41e 100644 --- a/Example/UICatalog/AAPLPageControlViewController.m +++ b/Example/UICatalog/AAPLPageControlViewController.m @@ -52,7 +52,7 @@ @interface AAPLPageControlViewController () @property (nonatomic, weak) IBOutlet UIPageControl *pageControl; @property (nonatomic, weak) IBOutlet UIView *colorView; -@property (nonatomic, strong) NSArray *colors; +@property (nonatomic) NSArray *colors; @end From f7619cdbf2c673635654db826af061cf79878140 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei <6d0847b9@opayq.com> Date: Fri, 16 Aug 2019 23:59:45 +0300 Subject: [PATCH 07/45] Fix build errors when using UIKit for Mac (Catalyst) --- Classes/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Classes/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h b/Classes/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h index c4a519fe24..8da9b84aef 100644 --- a/Classes/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h +++ b/Classes/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h @@ -24,11 +24,13 @@ * * See for details. */ +#if !TARGET_OS_MACCATALYST #if OS_OBJECT_USE_OBJC OS_OBJECT_DECL(xpc_object); #else typedef void * xpc_object_t; -#endif +#endif +#endif #define OS_ACTIVITY_MAX_CALLSTACK 32 From e7290bc84f179bc00b248f82b20e0bfaa99ce0bd Mon Sep 17 00:00:00 2001 From: Iulian Onofrei <6d0847b9@opayq.com> Date: Sat, 17 Aug 2019 02:04:23 +0300 Subject: [PATCH 08/45] Fix build error --- Classes/Manager/FLEXManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 9d50190817..b28731f7f0 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -86,7 +86,7 @@ - (void)showExplorer // Look for an active UIWindowScene if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { - self.explorerWindow.windowScene = (UIWindowScene)scene; + self.explorerWindow.windowScene = (UIWindowScene *)scene; break; } } From bba5b8b72cc5a2ffac021497add614601966975e Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 12:50:52 -0700 Subject: [PATCH 09/45] Remove absolute path from FLEX.codeproj --- FLEX.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 4bf7fb9440..95b04583bc 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -391,12 +391,12 @@ C3511B9022D7C99E0057BAB7 /* FLEXTableViewSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewSection.m; sourceTree = ""; }; C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjcInternal.h; sourceTree = ""; }; C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FLEXObjcInternal.mm; sourceTree = ""; }; - C387C87822DFCD6A00750E58 /* FLEXCarouselCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXCarouselCell.h; path = ../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Core/FLEXCarouselCell.h; sourceTree = ""; }; - C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXCarouselCell.m; path = ../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Core/FLEXCarouselCell.m; sourceTree = ""; }; - C387C87C22DFD71A00750E58 /* FLEXClassTreeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXClassTreeViewController.h; path = ../../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/ObjectExplorers/Controllers/FLEXClassTreeViewController.h; sourceTree = ""; }; - C387C87D22DFD71A00750E58 /* FLEXClassTreeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXClassTreeViewController.m; path = ../../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/ObjectExplorers/Controllers/FLEXClassTreeViewController.m; sourceTree = ""; }; - C387C88122E0D24A00750E58 /* UIView+Layout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIView+Layout.h"; path = "../../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Utility/Categories/UIView+Layout.h"; sourceTree = ""; }; - C387C88222E0D24A00750E58 /* UIView+Layout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIView+Layout.m"; path = "../../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Utility/Categories/UIView+Layout.m"; sourceTree = ""; }; + C387C87822DFCD6A00750E58 /* FLEXCarouselCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXCarouselCell.h; path = FLEXCarouselCell.h; sourceTree = ""; }; + C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXCarouselCell.m; path = FLEXCarouselCell.m; sourceTree = ""; }; + C387C87C22DFD71A00750E58 /* FLEXClassTreeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXClassTreeViewController.h; path = FLEXClassTreeViewController.h; sourceTree = ""; }; + C387C87D22DFD71A00750E58 /* FLEXClassTreeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXClassTreeViewController.m; path = FLEXClassTreeViewController.m; sourceTree = ""; }; + C387C88122E0D24A00750E58 /* UIView+Layout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIView+Layout.h"; path = "UIView+Layout.h"; sourceTree = ""; }; + C387C88222E0D24A00750E58 /* UIView+Layout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIView+Layout.m"; path = "UIView+Layout.m"; sourceTree = ""; }; C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewController.h; sourceTree = ""; }; C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewController.m; sourceTree = ""; }; C395D6D721789BD800BEAD4D /* FLEXColorExplorerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXColorExplorerViewController.h; sourceTree = ""; }; @@ -407,8 +407,8 @@ C3DA55FD21A76406005DDA60 /* FLEXMutableFieldEditorViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXMutableFieldEditorViewController.m; sourceTree = ""; }; C3DB9F622107FC9600B46809 /* FLEXObjectRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjectRef.h; sourceTree = ""; }; C3DB9F632107FC9600B46809 /* FLEXObjectRef.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectRef.m; sourceTree = ""; }; - C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXScopeCarousel.h; path = ../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Core/FLEXScopeCarousel.h; sourceTree = ""; }; - C3EE76BE22DFC63600EC0AA0 /* FLEXScopeCarousel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXScopeCarousel.m; path = ../../../../../../System/Volumes/Data/Users/tanner/Repos/FLEX/Classes/Core/FLEXScopeCarousel.m; sourceTree = ""; }; + C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXScopeCarousel.h; path = FLEXScopeCarousel.h; sourceTree = ""; }; + C3EE76BE22DFC63600EC0AA0 /* FLEXScopeCarousel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXScopeCarousel.m; path = FLEXScopeCarousel.m; sourceTree = ""; }; C3F31D342267D883003C991A /* FLEXSubtitleTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSubtitleTableViewCell.h; sourceTree = ""; }; C3F31D352267D883003C991A /* FLEXTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewCell.h; sourceTree = ""; }; C3F31D362267D883003C991A /* FLEXMultilineTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMultilineTableViewCell.h; sourceTree = ""; }; From 4c2e921f9eac65a5eeeec424f3b26eb90cd68507 Mon Sep 17 00:00:00 2001 From: "Ryan Olson (IG)" Date: Sun, 18 Aug 2019 12:56:06 -0700 Subject: [PATCH 10/45] Bump deployment target to 9.0 --- Example/UICatalog.xcodeproj/project.pbxproj | 2 ++ FLEX.podspec | 2 +- FLEX.xcodeproj/project.pbxproj | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Example/UICatalog.xcodeproj/project.pbxproj b/Example/UICatalog.xcodeproj/project.pbxproj index 5441d4c41b..5133313fda 100644 --- a/Example/UICatalog.xcodeproj/project.pbxproj +++ b/Example/UICatalog.xcodeproj/project.pbxproj @@ -594,6 +594,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "UICatalog/UICatalog-Prefix.pch"; INFOPLIST_FILE = "UICatalog/UICatalog-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEX.example2; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -617,6 +618,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "UICatalog/UICatalog-Prefix.pch"; INFOPLIST_FILE = "UICatalog/UICatalog-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEX.example2; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/FLEX.podspec b/FLEX.podspec index aff4e69cdc..ed71a3d6cb 100644 --- a/FLEX.podspec +++ b/FLEX.podspec @@ -29,7 +29,7 @@ Pod::Spec.new do |spec| spec.license = { :type => "BSD", :file => "LICENSE" } spec.author = { "Tanner Bennett" => "tannerbennett@me.com" } spec.social_media_url = "https://twitter.com/NSExceptional" - spec.platform = :ios, "8.0" + spec.platform = :ios, "9.0" spec.source = { :git => "https://github.com/Flipboard/FLEX.git", :tag => "#{spec.version}" } spec.source_files = "Classes/**/*.{h,m,mm}" spec.frameworks = [ "Foundation", "UIKit", "CoreGraphics", "ImageIO", "QuartzCore", "WebKit" ] diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 95b04583bc..5e0cea2b3e 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -1327,6 +1327,7 @@ ); INFOPLIST_FILE = Classes/Info.plist; INSTALL_PATH = "@rpath"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.flipboard.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1353,6 +1354,7 @@ ); INFOPLIST_FILE = Classes/Info.plist; INSTALL_PATH = "@rpath"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.flipboard.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; From 74eb6e180b3bbd30d850661ccb0255aeb2db9b55 Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 12:10:25 -0700 Subject: [PATCH 11/45] Use FLEXTypeEncoding enum and kFLEXUtilityAttribute whenever possible --- .../FLEXArgumentInputStructView.m | 6 +- .../FLEXInstancesTableViewController.m | 2 +- Classes/Utility/FLEXRuntimeUtility.h | 9 +- Classes/Utility/FLEXRuntimeUtility.m | 148 +++++++++--------- 4 files changed, 84 insertions(+), 81 deletions(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m index aa35b606d0..b1480022f7 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m @@ -74,7 +74,7 @@ - (void)setInputValue:(id)inputValue void *fieldPointer = unboxedValue + fieldOffset; FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex]; - if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) { + if (fieldTypeEncoding[0] == FLEXTypeEncodingObjcObject || fieldTypeEncoding[0] == FLEXTypeEncodingObjcClass) { inputView.inputValue = (__bridge id)fieldPointer; } else { NSValue *boxedField = [FLEXRuntimeUtility valueForPrimitivePointer:fieldPointer objCType:fieldTypeEncoding]; @@ -104,7 +104,7 @@ - (id)inputValue void *fieldPointer = unboxedStruct + fieldOffset; FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex]; - if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) { + if (fieldTypeEncoding[0] == FLEXTypeEncodingObjcObject || fieldTypeEncoding[0] == FLEXTypeEncodingObjcClass) { // Object fields memcpy(fieldPointer, (__bridge void *)inputView.inputValue, sizeof(id)); } else { @@ -176,7 +176,7 @@ - (CGSize)sizeThatFits:(CGSize)size + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - return type && type[0] == '{'; + return type && type[0] == FLEXTypeEncodingStructBegin; } + (NSArray *)customFieldTitlesForTypeEncoding:(const char *)typeEncoding diff --git a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m index 9146094cb6..f88a38fe58 100644 --- a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m @@ -93,7 +93,7 @@ + (instancetype)instancesTableViewControllerForInstancesReferencingObject:(id)ob for (unsigned int ivarIndex = 0; ivarIndex < ivarCount; ivarIndex++) { Ivar ivar = ivars[ivarIndex]; const char *typeEncoding = ivar_getTypeEncoding(ivar); - if (typeEncoding[0] == @encode(id)[0] || typeEncoding[0] == @encode(Class)[0]) { + if (typeEncoding[0] == FLEXTypeEncodingObjcObject || typeEncoding[0] == FLEXTypeEncodingObjcClass) { ptrdiff_t offset = ivar_getOffset(ivar); uintptr_t *fieldPointer = (__bridge void *)tryObject + offset; if (*fieldPointer == (uintptr_t)(__bridge void *)object) { diff --git a/Classes/Utility/FLEXRuntimeUtility.h b/Classes/Utility/FLEXRuntimeUtility.h index 7590f8a2c0..218373f875 100644 --- a/Classes/Utility/FLEXRuntimeUtility.h +++ b/Classes/Utility/FLEXRuntimeUtility.h @@ -46,9 +46,12 @@ typedef NS_ENUM(char, FLEXTypeEncoding) FLEXTypeEncodingObjcObject = '@', FLEXTypeEncodingObjcClass = '#', FLEXTypeEncodingSelector = ':', - FLEXTypeEncodingArray = '[', - FLEXTypeEncodingStruct = '{', - FLEXTypeEncodingUnion = '(', + FLEXTypeEncodingArrayBegin = '[', + FLEXTypeEncodingArrayEnd = ']', + FLEXTypeEncodingStructBegin = '{', + FLEXTypeEncodingStructEnd = '}', + FLEXTypeEncodingUnionBegin = '(', + FLEXTypeEncodingUnionEnd = ')', FLEXTypeEncodingBitField = 'b', FLEXTypeEncodingPointer = '^', FLEXTypeEncodingConst = 'r' diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 7769ea695c..ccaa133914 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -49,18 +49,18 @@ + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXType if (!returnedObjectOrNil) { return nil; } - + NSInteger i = 0; if (returnType[i] == FLEXTypeEncodingConst) { i++; } - + BOOL returnsObjectOrClass = returnType[i] == FLEXTypeEncodingObjcObject || returnType[i] == FLEXTypeEncodingObjcClass; BOOL returnsVoidPointer = returnType[i] == FLEXTypeEncodingPointer && returnType[i+1] == FLEXTypeEncodingVoid; BOOL returnsCString = returnType[i] == FLEXTypeEncodingCString; - + // If we got back an NSValue and the return type is not an object, // we check to see if the pointer is of a valid object. If not, // we just display the NSValue. @@ -70,9 +70,9 @@ + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXType if (![returnedObjectOrNil isKindOfClass:[NSValue class]]) { return returnedObjectOrNil; } - + NSValue *value = (NSValue *)returnedObjectOrNil; - + if (returnsCString) { // Wrap char * in NSString const char *string = (const char *)value.pointerValue; @@ -84,7 +84,7 @@ + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXType } } } - + return returnedObjectOrNil; } @@ -138,14 +138,14 @@ + (NSString *)fullDescriptionForProperty:(objc_property_t)property { NSDictionary *attributesDictionary = [self attributesDictionaryForProperty:property]; NSMutableArray *attributesStrings = [NSMutableArray array]; - + // Atomicity if (attributesDictionary[kFLEXUtilityAttributeNonAtomic]) { [attributesStrings addObject:@"nonatomic"]; } else { [attributesStrings addObject:@"atomic"]; } - + // Storage if (attributesDictionary[kFLEXUtilityAttributeRetain]) { [attributesStrings addObject:@"strong"]; @@ -156,14 +156,14 @@ + (NSString *)fullDescriptionForProperty:(objc_property_t)property } else { [attributesStrings addObject:@"assign"]; } - + // Mutability if (attributesDictionary[kFLEXUtilityAttributeReadOnly]) { [attributesStrings addObject:@"readonly"]; } else { [attributesStrings addObject:@"readwrite"]; } - + // Custom getter/setter NSString *customGetter = attributesDictionary[kFLEXUtilityAttributeCustomGetter]; NSString *customSetter = attributesDictionary[kFLEXUtilityAttributeCustomSetter]; @@ -173,22 +173,22 @@ + (NSString *)fullDescriptionForProperty:(objc_property_t)property if (customSetter) { [attributesStrings addObject:[NSString stringWithFormat:@"setter=%@", customSetter]]; } - + NSString *attributesString = [attributesStrings componentsJoinedByString:@", "]; NSString *shortName = [self prettyNameForProperty:property]; - + return [NSString stringWithFormat:@"@property (%@) %@", attributesString, shortName]; } + (id)valueForProperty:(objc_property_t)property onObject:(id)object { NSString *customGetterString = nil; - char *customGetterName = property_copyAttributeValue(property, "G"); + char *customGetterName = property_copyAttributeValue(property, kFLEXUtilityAttributeCustomGetter.UTF8String); if (customGetterName) { customGetterString = @(customGetterName); free(customGetterName); } - + SEL getterSelector; if (customGetterString.length > 0) { getterSelector = NSSelectorFromString(customGetterString); @@ -196,14 +196,14 @@ + (id)valueForProperty:(objc_property_t)property onObject:(id)object NSString *propertyName = @(property_getName(property)); getterSelector = NSSelectorFromString(propertyName); } - + return [self performSelector:getterSelector onObject:object withArguments:nil error:NULL]; } + (NSString *)descriptionForIvarOrPropertyValue:(id)value { NSString *description = nil; - + // Special case BOOL for better readability. if ([value isKindOfClass:[NSValue class]]) { const char *type = [value objCType]; @@ -217,7 +217,7 @@ + (NSString *)descriptionForIvarOrPropertyValue:(id)value description = NSStringFromSelector(selector); } } - + @try { if (!description) { // Single line display - replace newlines and tabs with spaces. @@ -227,11 +227,11 @@ + (NSString *)descriptionForIvarOrPropertyValue:(id)value } @catch (NSException *e) { description = [@"Thrown: " stringByAppendingString:e.reason ?: @"(nil exception reason)"]; } - + if (!description) { description = @"nil"; } - + return description; } @@ -249,7 +249,7 @@ + (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary *)prettyArgumentComponentsForMethod:(Method)method { NSMutableArray *components = [NSMutableArray array]; - + NSString *selectorName = NSStringFromSelector(method_getName(method)); NSMutableArray *selectorComponents = [[selectorName componentsSeparatedByString:@":"] mutableCopy]; - + // this is a workaround cause method_getNumberOfArguments() returns wrong number for some methods if (selectorComponents.count == 1) { return @[]; } - + if ([selectorComponents.lastObject isEqualToString:@""]) { [selectorComponents removeLastObject]; } - + for (unsigned int argIndex = 0; argIndex < selectorComponents.count; argIndex++) { char *argType = method_copyArgumentType(method, argIndex + kFLEXNumberOfImplicitArgs); NSString *readableArgType = (argType != NULL) ? [self readableTypeForEncoding:@(argType)] : nil; @@ -362,7 +362,7 @@ + (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMeth NSString *prettyComponent = [NSString stringWithFormat:@"%@:(%@) ", [selectorComponents objectAtIndex:argIndex], readableArgType]; [components addObject:prettyComponent]; } - + return components; } @@ -384,24 +384,24 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * } return nil; } - + // Build the invocation NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setSelector:selector]; [invocation setTarget:object]; [invocation retainArguments]; - + // Always self and _cmd NSUInteger numberOfArguments = [methodSignature numberOfArguments]; for (NSUInteger argumentIndex = kFLEXNumberOfImplicitArgs; argumentIndex < numberOfArguments; argumentIndex++) { NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs; id argumentObject = arguments.count > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil; - + // NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil. if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) { const char *typeEncodingCString = [methodSignature getArgumentTypeAtIndex:argumentIndex]; - if (typeEncodingCString[0] == @encode(id)[0] || typeEncodingCString[0] == @encode(Class)[0] || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { + if (typeEncodingCString[0] == FLEXTypeEncodingObjcObject || typeEncodingCString[0] == FLEXTypeEncodingObjcClass || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { // Object [invocation setArgument:&argumentObject atIndex:argumentIndex]; } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 && [argumentObject isKindOfClass:[UIColor class]]) { @@ -411,7 +411,7 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * } else if ([argumentObject isKindOfClass:[NSValue class]]) { // Primitive boxed in NSValue NSValue *argumentValue = (NSValue *)argumentObject; - + // Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature if (strcmp([argumentValue objCType], typeEncodingCString) != 0) { if (error) { @@ -420,13 +420,13 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * } return nil; } - + @try { NSUInteger bufferSize = 0; - + // NSGetSizeAndAlignment barfs on type encoding for bitfields. NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL); - + if (bufferSize > 0) { void *buffer = calloc(bufferSize, 1); [argumentValue getValue:buffer]; @@ -437,26 +437,26 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * } } } - + // Try to invoke the invocation but guard against an exception being thrown. id returnObject = nil; @try { // Some methods are not fit to be called... // Looking at you -[UIResponder(UITextInputAdditions) _caretRect] [invocation invoke]; - + // Retrieve the return value and box if necessary. const char *returnType = methodSignature.methodReturnType; - - if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) { + + if (returnType[0] == FLEXTypeEncodingObjcObject || returnType[0] == FLEXTypeEncodingObjcClass) { // Return value is an object. __unsafe_unretained id objectReturnedFromMethod = nil; [invocation getReturnValue:&objectReturnedFromMethod]; returnObject = objectReturnedFromMethod; - } else if (returnType[0] != @encode(void)[0]) { + } else if (returnType[0] != FLEXTypeEncodingVoid) { // Will use arbitrary buffer for return value and box it. void *returnValue = malloc(methodSignature.methodReturnLength); - + if (returnValue) { [invocation getReturnValue:returnValue]; returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType]; @@ -469,19 +469,19 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * // "… on " / "… on instance of " NSString *class = NSStringFromClass([object class]); NSString *calledOn = object == [object class] ? class : [@"an instance of " stringByAppendingString:class]; - + NSString *message = [NSString stringWithFormat:@"Exception '%@' thrown while performing selector '%@' on %@.\nReason:\n\n%@", exception.name, NSStringFromSelector(selector), calledOn, exception.reason]; - + *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeInvocationFailed userInfo:@{ NSLocalizedDescriptionKey : message }]; } } - + return returnObject; } @@ -492,7 +492,7 @@ + (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding if(strcmp(typeEncoding, @encode(cftype)) == 0) { \ return [value isKindOfClass:[foundationClass class]]; \ } - + CASE(CFArrayRef, NSArray); CASE(CFAttributedStringRef, NSAttributedString); CASE(CFCalendarRef, NSCalendar); @@ -517,16 +517,16 @@ + (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding CASE(CFTimeZoneRef, NSTimeZone); CASE(CFURLRef, NSURL); CASE(CFWriteStreamRef, NSOutputStream); - + #undef CASE - + return NO; } + (NSString *)editableJSONStringForObject:(id)object { NSString *editableDescription = nil; - + if (object) { // This is a hack to use JSON serialization for our editable objects. // NSJSONSerialization doesn't allow writing fragments - the top level object must be an array or dictionary. @@ -537,7 +537,7 @@ + (NSString *)editableJSONStringForObject:(id)object editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, wrappedDescription.length - 2)]; } } - + return editableDescription; } @@ -556,7 +556,7 @@ + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputStri NSNumberFormatter *formatter = [NSNumberFormatter new]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; NSNumber *number = [formatter numberFromString:inputString]; - + // Make sure we box the number with the correct type encoding so it can be properly unboxed later via getValue: NSValue *value = nil; if (strcmp(typeEncoding, @encode(char)) == 0) { @@ -596,30 +596,30 @@ + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputStri double primitiveValue = [number doubleValue]; value = [NSValue value:&primitiveValue withObjCType:typeEncoding]; } - + return value; } + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock { - if (structEncoding && structEncoding[0] == '{') { + if (structEncoding && structEncoding[0] == FLEXTypeEncodingStructBegin) { const char *equals = strchr(structEncoding, '='); if (equals) { const char *nameStart = structEncoding + 1; NSString *structName = [@(structEncoding) substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)]; - + NSUInteger fieldAlignment = 0; NSUInteger structSize = 0; @try { // NSGetSizeAndAlignment barfs on type encoding for bitfields. NSGetSizeAndAlignment(structEncoding, &structSize, &fieldAlignment); } @catch (NSException *exception) { } - + if (structSize > 0) { NSUInteger runningFieldIndex = 0; NSUInteger runningFieldOffset = 0; const char *typeStart = equals + 1; - while (*typeStart != '}') { + while (*typeStart != FLEXTypeEncodingStructEnd) { NSUInteger fieldSize = 0; // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here. const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL); @@ -670,32 +670,32 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString if (!encodingString) { return nil; } - + // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html // class-dump has a much nicer and much more complete implementation for this task, but it is distributed under GPLv2 :/ // See https://github.com/nygard/class-dump/blob/master/Source/CDType.m // Warning: this method uses multiple middle returns and macros to cut down on boilerplate. // The use of macros here was inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html const char *encodingCString = encodingString.UTF8String; - + // Objects - if (encodingCString[0] == '@') { + if (encodingCString[0] == FLEXTypeEncodingObjcObject) { NSString *class = [encodingString substringFromIndex:1]; class = [class stringByReplacingOccurrencesOfString:@"\"" withString:@""]; - if (class.length == 0 || [class isEqual:@"?"]) { + if (class.length == 0 || (class.length == 1 && [class characterAtIndex:0] == FLEXTypeEncodingUnknown)) { class = @"id"; } else { class = [class stringByAppendingString:@" *"]; } return class; } - + // C Types #define TRANSLATE(ctype) \ if (strcmp(encodingCString, @encode(ctype)) == 0) { \ return (NSString *)CFSTR(#ctype); \ } - + // Order matters here since some of the cocoa types are typedefed to c types. // We can't recover the exact mapping, but we choose to prefer the cocoa types. // This is not an exhaustive list, but it covers the most common types @@ -735,9 +735,9 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString TRANSLATE(NSZone *); TRANSLATE(SEL); TRANSLATE(void); - + #undef TRANSLATE - + // Qualifier Prefixes // Do this after the checks above since some of the direct translations (i.e. Method) contain a prefix. #define RECURSIVE_TRANSLATE(prefix, formatString) \ @@ -745,7 +745,7 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString NSString *recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:1]]; \ return [NSString stringWithFormat:formatString, recursiveType]; \ } - + // If there's a qualifier prefix on the encoding, translate it and then // recursively call this method with the rest of the encoding string. RECURSIVE_TRANSLATE('^', @"%@ *"); @@ -757,9 +757,9 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString RECURSIVE_TRANSLATE('R', @"byref %@"); RECURSIVE_TRANSLATE('V', @"oneway %@"); RECURSIVE_TRANSLATE('b', @"bitfield(%@)"); - + #undef RECURSIVE_TRANSLATE - + // If we couldn't translate, just return the original encoding string return encodingString; } @@ -771,7 +771,7 @@ + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)typ if(strcmp(type, @encode(ctype)) == 0) { \ return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \ } - + CASE(BOOL, Bool); CASE(unsigned char, UnsignedChar); CASE(short, Short); @@ -784,16 +784,16 @@ + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)typ CASE(unsigned long long, UnsignedLongLong); CASE(float, Float); CASE(double, Double); - + #undef CASE - + NSValue *value = nil; @try { value = [NSValue valueWithBytes:pointer objCType:type]; } @catch (NSException *exception) { // Certain type encodings are not supported by valueWithBytes:objCType:. Just fail silently if an exception is thrown. } - + return value; } From 40b52120d049cebd1e52625f19141d43f0be0f03 Mon Sep 17 00:00:00 2001 From: "Ryan Olson (IG)" Date: Sun, 18 Aug 2019 13:12:44 -0700 Subject: [PATCH 12/45] Update version numbers in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 17f7917a59..e5b5046841 100644 --- a/README.md +++ b/README.md @@ -121,14 +121,14 @@ The code injection is left as an exercise for the reader. :innocent: ## Installation -FLEX requires an app that targets iOS 7 or higher. +FLEX requires an app that targets iOS 9 or higher. ### CocoaPods FLEX is available on [CocoaPods](https://cocoapods.org/pods/FLEX). Simply add the following line to your podfile: ```ruby -pod 'FLEX', '~> 2.0', :configurations => ['Debug'] +pod 'FLEX', '~> 3.0', :configurations => ['Debug'] ``` ### Carthage @@ -136,7 +136,7 @@ pod 'FLEX', '~> 2.0', :configurations => ['Debug'] Add the following to your Cartfile: ``` -github "flipboard/FLEX" ~> 2.0 +github "flipboard/FLEX" ~> 3.0 ``` ### Manual From 3650da6c12fa7e4f17cb7ccb60787c6d9b416da3 Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 13:22:30 -0700 Subject: [PATCH 13/45] Remove support for long-deprecated global status bar management --- .../FLEXExplorerViewController.m | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 50be3a17b9..8468e4e6b3 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -61,12 +61,6 @@ @interface FLEXExplorerViewController () *observedViews; @@ -799,12 +793,6 @@ - (void)makeKeyAndPresentViewController:(UIViewController *)viewController anima // Move the status bar on top of FLEX so we can get scroll to top behavior for taps. [[self statusWindow] setWindowLevel:self.view.window.windowLevel + 1.0]; - // If this app doesn't use view controller based status bar management and we're on iOS 7+, - // make sure the status bar style is UIStatusBarStyleDefault. We don't actually have to check - // for view controller based management because the global methods no-op if that is turned on. - self.previousStatusBarStyle = [UIApplication.sharedApplication statusBarStyle]; - [UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleDefault]; - // Show the view controller. [self presentViewController:viewController animated:animated completion:completion]; } @@ -820,9 +808,6 @@ - (void)resignKeyAndDismissViewControllerAnimated:(BOOL)animated completion:(voi // We want it above FLEX while a modal is presented for scroll to top, but below FLEX otherwise for exploration. [[self statusWindow] setWindowLevel:UIWindowLevelStatusBar]; - // Restore the status bar style if the app is using global status bar management. - [UIApplication.sharedApplication setStatusBarStyle:self.previousStatusBarStyle]; - [self dismissViewControllerAnimated:animated completion:completion]; } From 32c0983bb72e4f42813ef4bf63642e72689ed7f5 Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:15:11 -0700 Subject: [PATCH 14/45] Let Xcode make the changes it wants to the project files --- .../xcshareddata/xcschemes/UICatalog.xcscheme | 10 +++------- FLEX.xcodeproj/project.pbxproj | 18 +++++++++--------- .../xcshareddata/xcschemes/FLEX.xcscheme | 10 +++------- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme b/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme index 909bb30e02..2f56d0c1a4 100644 --- a/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme +++ b/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme @@ -1,6 +1,6 @@ - - - - + + - - - - - - + + - - Date: Sun, 18 Aug 2019 19:07:54 -0700 Subject: [PATCH 15/45] Fix issues in FLEXRuntimeUtility --- Classes/Utility/FLEXRuntimeUtility.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index ccaa133914..05c8338a7a 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -76,7 +76,7 @@ + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXType if (returnsCString) { // Wrap char * in NSString const char *string = (const char *)value.pointerValue; - returnedObjectOrNil = [NSString stringWithCString:string encoding:NSUTF8StringEncoding]; + returnedObjectOrNil = string ? [NSString stringWithCString:string encoding:NSUTF8StringEncoding] : NULL; } else if (returnsVoidPointer) { // Cast valid objects disguised as void * to id if ([FLEXRuntimeUtility pointerIsValidObjcObject:value.pointerValue]) { @@ -489,7 +489,7 @@ + (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding { // See https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html #define CASE(cftype, foundationClass) \ - if(strcmp(typeEncoding, @encode(cftype)) == 0) { \ + if (strcmp(typeEncoding, @encode(cftype)) == 0) { \ return [value isKindOfClass:[foundationClass class]]; \ } @@ -657,7 +657,7 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( + (NSString *)appendName:(NSString *)name toType:(NSString *)type { NSString *combined = nil; - if ([type characterAtIndex:type.length - 1] == '*') { + if ([type characterAtIndex:type.length - 1] == FLEXTypeEncodingCString) { combined = [type stringByAppendingString:name]; } else { combined = [type stringByAppendingFormat:@" %@", name]; @@ -768,7 +768,7 @@ + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)typ { // CASE macro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html #define CASE(ctype, selectorpart) \ - if(strcmp(type, @encode(ctype)) == 0) { \ + if (strcmp(type, @encode(ctype)) == 0) { \ return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \ } From 9935860efbbe058f2ef35f4393c2ea86cf4aee7e Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 13:58:55 -0700 Subject: [PATCH 16/45] Fix struct field offset calculation when enumerating struct encoding --- Classes/Utility/FLEXRuntimeUtility.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 05c8338a7a..722937dfaf 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -624,13 +624,14 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here. const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL); NSString *typeEncoding = [@(structEncoding) substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)]; - typeBlock(structName, typeEncoding.UTF8String, [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset); - runningFieldOffset += fieldSize; // Padding to keep proper alignment. __attribute((packed)) structs will break here. // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those. - if (runningFieldOffset % fieldAlignment != 0) { - runningFieldOffset += fieldAlignment - runningFieldOffset % fieldAlignment; + const NSUInteger currentSizeSum = runningFieldOffset % fieldAlignment; + if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) { + runningFieldOffset += fieldAlignment - currentSizeSum; } + typeBlock(structName, typeEncoding.UTF8String, [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset); + runningFieldOffset += fieldSize; runningFieldIndex++; typeStart = nextTypeStart; } From 664a39e0f124c6e8c5eb668b05f842371fcb45d4 Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 20:30:12 -0700 Subject: [PATCH 17/45] Add CGVector and NSDirectionalEdgeInsets support --- .../ArgumentInputViews/FLEXArgumentInputStructView.m | 9 +++++++++ Classes/Utility/FLEXRuntimeUtility.m | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m index b1480022f7..f41e991ce3 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m @@ -188,6 +188,8 @@ + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value customTitles = @[@"CGFloat x", @"CGFloat y"]; } else if (strcmp(typeEncoding, @encode(CGSize)) == 0) { customTitles = @[@"CGFloat width", @"CGFloat height"]; + } else if (strcmp(typeEncoding, @encode(CGVector)) == 0) { + customTitles = @[@"CGFloat dx", @"CGFloat dy"]; } else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) { customTitles = @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"]; } else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) { @@ -203,6 +205,13 @@ + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value customTitles = @[@"CGFloat a", @"CGFloat b", @"CGFloat c", @"CGFloat d", @"CGFloat tx", @"CGFloat ty"]; + } else { + if (@available(iOS 11.0, *)) { + if (strcmp(typeEncoding, @encode(NSDirectionalEdgeInsets)) == 0) { + customTitles = @[@"CGFloat top", @"CGFloat leading", + @"CGFloat bottom", @"CGFloat trailing"]; + } + } } return customTitles; } diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 722937dfaf..97018a9ced 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -703,7 +703,11 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString TRANSLATE(CGRect); TRANSLATE(CGPoint); TRANSLATE(CGSize); + TRANSLATE(CGVector); TRANSLATE(UIEdgeInsets); + if (@available(iOS 11.0, *)) { + TRANSLATE(NSDirectionalEdgeInsets); + } TRANSLATE(UIOffset); TRANSLATE(NSRange); TRANSLATE(CGAffineTransform); From 5a54f5808d53ce53bb5c3a9c5a3a2e37d1c679c0 Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 20:17:43 -0700 Subject: [PATCH 18/45] Add long double support in FLEXRuntimeUtility --- .../Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m | 3 ++- Classes/Utility/FLEXRuntimeUtility.h | 1 + Classes/Utility/FLEXRuntimeUtility.m | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m index e584f667c1..a6bc207cdd 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m @@ -49,7 +49,8 @@ + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value @(@encode(unsigned long)), @(@encode(unsigned long long)), @(@encode(float)), - @(@encode(double))]; + @(@encode(double)), + @(@encode(long double))]; }); return type && [primitiveTypes containsObject:@(type)]; } diff --git a/Classes/Utility/FLEXRuntimeUtility.h b/Classes/Utility/FLEXRuntimeUtility.h index 218373f875..35f77f0a54 100644 --- a/Classes/Utility/FLEXRuntimeUtility.h +++ b/Classes/Utility/FLEXRuntimeUtility.h @@ -40,6 +40,7 @@ typedef NS_ENUM(char, FLEXTypeEncoding) FLEXTypeEncodingUnsignedLongLong = 'Q', FLEXTypeEncodingFloat = 'f', FLEXTypeEncodingDouble = 'd', + FLEXTypeEncodingLongDouble = 'D', FLEXTypeEncodingCBool = 'B', FLEXTypeEncodingVoid = 'v', FLEXTypeEncodingCString = '*', diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 97018a9ced..5ee9d30752 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -595,6 +595,9 @@ + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputStri } else if (strcmp(typeEncoding, @encode(double)) == 0) { double primitiveValue = [number doubleValue]; value = [NSValue value:&primitiveValue withObjCType:typeEncoding]; + } else if (strcmp(typeEncoding, @encode(long double)) == 0) { + long double primitiveValue = [number doubleValue]; + value = [NSValue value:&primitiveValue withObjCType:typeEncoding]; } return value; @@ -789,6 +792,7 @@ + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)typ CASE(unsigned long long, UnsignedLongLong); CASE(float, Float); CASE(double, Double); + CASE(long double, Double); #undef CASE From b5d5867bc17a01903c18e3a86d472ac06d9c21bb Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:20:02 -0700 Subject: [PATCH 19/45] Convert alerts in FLEXNetworkTransactionDetailTVC to UIAlertController --- ...workTransactionDetailTableViewController.m | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m index 4664dcdbaa..c051ef9418 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m @@ -162,13 +162,15 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath { FLEXNetworkDetailRow *rowModel = [self rowModelAtIndexPath:indexPath]; - UIViewController *viewControllerToPush = nil; + UIViewController *viewController = nil; if (rowModel.selectionFuture) { - viewControllerToPush = rowModel.selectionFuture(); + viewController = rowModel.selectionFuture(); } - if (viewControllerToPush) { - [self.navigationController pushViewController:viewControllerToPush animated:YES]; + if ([viewController isKindOfClass:UIAlertController.class]) { + [self presentViewController:viewController animated:YES completion:nil]; + } else if (viewController) { + [self.navigationController pushViewController:viewController animated:YES]; } [tableView deselectRowAtIndexPath:indexPath animated:YES]; @@ -257,16 +259,20 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti FLEXNetworkDetailRow *postBodyRow = [FLEXNetworkDetailRow new]; postBodyRow.title = @"Request Body"; postBodyRow.detailText = @"tap to view"; - postBodyRow.selectionFuture = ^{ + postBodyRow.selectionFuture = ^UIViewController * (void){ NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; UIViewController *detailViewController = [self detailViewControllerForMIMEType:contentType data:[self postBodyDataForTransaction:transaction]]; if (detailViewController) { detailViewController.title = @"Request Body"; - } else { - NSString *alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for request body data with MIME type: %@", [transaction.request valueForHTTPHeaderField:@"Content-Type"]]; - [[[UIAlertView alloc] initWithTitle:@"Can't View Body Data" message:alertMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; + return detailViewController; } - return detailViewController; + + NSString *alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for request body data with MIME type: %@", [transaction.request valueForHTTPHeaderField:@"Content-Type"]]; + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Can't View Body Data" + message:alertMessage + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; + return alert; }; [rows addObject:postBodyRow]; } @@ -293,21 +299,26 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti responseBodyRow.detailText = @"tap to view"; // Avoid a long lived strong reference to the response data in case we need to purge it from the cache. __weak NSData *weakResponseData = responseData; - responseBodyRow.selectionFuture = ^{ - UIViewController *responseBodyDetailViewController = nil; + responseBodyRow.selectionFuture = ^UIViewController * (void){ + NSString *alertMessage = nil; NSData *strongResponseData = weakResponseData; if (strongResponseData) { - responseBodyDetailViewController = [self detailViewControllerForMIMEType:transaction.response.MIMEType data:strongResponseData]; - if (!responseBodyDetailViewController) { - NSString *alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for responses with MIME type: %@", transaction.response.MIMEType]; - [[[UIAlertView alloc] initWithTitle:@"Can't View Response" message:alertMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; + UIViewController *responseBodyDetailViewController = [self detailViewControllerForMIMEType:transaction.response.MIMEType data:strongResponseData]; + if (responseBodyDetailViewController) { + responseBodyDetailViewController.title = @"Response"; + return responseBodyDetailViewController; } - responseBodyDetailViewController.title = @"Response"; + + alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for responses with MIME type: %@", transaction.response.MIMEType]; } else { - NSString *alertMessage = @"The response has been purged from the cache"; - [[[UIAlertView alloc] initWithTitle:@"Can't View Response" message:alertMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; + alertMessage = @"The response has been purged from the cache"; } - return responseBodyDetailViewController; + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Can't View Response" + message:alertMessage + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; + return alert; }; } else { BOOL emptyResponse = transaction.receivedDataLength == 0; From 89b9ece45d22ee5ae04ef097ef69305129ffed5d Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:25:21 -0700 Subject: [PATCH 20/45] Convert network settings action sheet to UIAlertController --- .../FLEXNetworkSettingsTableViewController.m | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Classes/Network/FLEXNetworkSettingsTableViewController.m b/Classes/Network/FLEXNetworkSettingsTableViewController.m index f1a6f6552c..9cfa6829e3 100644 --- a/Classes/Network/FLEXNetworkSettingsTableViewController.m +++ b/Classes/Network/FLEXNetworkSettingsTableViewController.m @@ -74,8 +74,14 @@ - (void)cacheLimitAdjusted:(UISlider *)sender - (void)clearRequestsTapped:(UIButton *)sender { - UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Clear Recorded Requests" otherButtonTitles:nil]; - [actionSheet showInView:self.view]; + UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [actionSheet addAction:[UIAlertAction actionWithTitle:@"Clear Recorded Requests" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [[FLEXNetworkRecorder defaultRecorder] clearRecordedActivity]; + }]]; + self.popoverPresentationController.sourceView = sender; + self.popoverPresentationController.sourceRect = sender.bounds; + [self presentViewController:actionSheet animated:YES completion:nil]; } #pragma mark - Table view data source @@ -95,15 +101,6 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N return self.cells[indexPath.row]; } -#pragma mark - UIActionSheetDelegate - -- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if (buttonIndex != actionSheet.cancelButtonIndex) { - [[FLEXNetworkRecorder defaultRecorder] clearRecordedActivity]; - } -} - #pragma mark - Helpers - (UITableViewCell *)switchCellWithTitle:(NSString *)title toggleAction:(SEL)toggleAction isOn:(BOOL)isOn From a58314a8255b4c3f606a058205265586afdebe0a Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:35:46 -0700 Subject: [PATCH 21/45] Convert alerts in file browser/FLEXUtility to UIAlertController --- .../FileBrowser/FLEXFileBrowserTableViewController.m | 10 ++-------- Classes/Utility/FLEXUtility.m | 8 +++----- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index 59c32b9c20..e0df9efed7 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -104,12 +104,6 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { } } -#pragma mark - Misc - -- (void)alert:(NSString *)title message:(NSString *)message { - [[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; -} - #pragma mark - FLEXFileBrowserSearchOperationDelegate - (void)fileBrowserSearchOperationResult:(NSArray *)searchResult size:(uint64_t)size @@ -218,7 +212,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath UIImage *image = cell.imageView.image; if (!stillExists) { - [self alert:@"File Not Found" message:@"The file at the specified path no longer exists."]; + [FLEXUtility alert:@"File Not Found" message:@"The file at the specified path no longer exists." from:self]; [self reloadDisplayedPaths]; return; } @@ -231,7 +225,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } else { NSData *fileData = [NSData dataWithContentsOfFile:fullPath]; if (!fileData.length) { - [self alert:@"Empty File" message:@"No data returned from the file."]; + [FLEXUtility alert:@"Empty File" message:@"No data returned from the file." from:self]; return; } diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index 0a38362117..b5b187c4c7 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -413,11 +413,9 @@ + (NSArray *)map:(NSArray *)array block:(id(^)(id obj, NSUInteger idx))mapFunc + (void)alert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController { - [[[UIAlertView alloc] initWithTitle:title - message:message - delegate:nil - cancelButtonTitle:nil - otherButtonTitles:@"Dismiss", nil] show]; + UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleDefault handler:nil]]; + [viewController presentViewController:alert animated:YES completion:nil]; } + (SEL)swizzledSelectorForSelector:(SEL)selector From 16fbab783ed1c8e20a6d459572ba47fe605954d9 Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:56:45 -0700 Subject: [PATCH 22/45] Convert file browser delete/rename to UIAlertController --- .../Editing/FLEXMethodCallingViewController.m | 6 +- .../FLEXFileBrowserFileOperationController.h | 33 ---- .../FLEXFileBrowserFileOperationController.m | 142 ------------------ .../FLEXFileBrowserTableViewController.m | 53 +++++-- FLEX.xcodeproj/project.pbxproj | 8 - 5 files changed, 39 insertions(+), 203 deletions(-) delete mode 100644 Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.h delete mode 100644 Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m diff --git a/Classes/Editing/FLEXMethodCallingViewController.m b/Classes/Editing/FLEXMethodCallingViewController.m index 6da66d2f61..aa8a1595ce 100644 --- a/Classes/Editing/FLEXMethodCallingViewController.m +++ b/Classes/Editing/FLEXMethodCallingViewController.m @@ -13,6 +13,7 @@ #import "FLEXObjectExplorerViewController.h" #import "FLEXArgumentInputView.h" #import "FLEXArgumentInputViewFactory.h" +#import "FLEXUtility.h" @interface FLEXMethodCallingViewController () @@ -94,10 +95,7 @@ - (void)actionButtonPressed:(id)sender id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:&error]; if (error) { - NSString *title = @"Method Call Failed"; - NSString *message = [error localizedDescription]; - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alert show]; + [FLEXUtility alert:@"Method Call Failed" message:[error localizedDescription] from:self]; } else if (returnedObject) { // For non-nil (or void) return types, push an explorer view controller to display the returned object returnedObject = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnedObject type:self.returnType]; diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.h b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.h deleted file mode 100644 index 79ff1144d5..0000000000 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// FLEXFileBrowserFileOperationController.h -// Flipboard -// -// Created by Daniel Rodriguez Troitino on 2/13/15. -// Copyright (c) 2015 Flipboard. All rights reserved. -// - -#import - -@protocol FLEXFileBrowserFileOperationController; - -@protocol FLEXFileBrowserFileOperationControllerDelegate - -- (void)fileOperationControllerDidDismiss:(id)controller; - -@end - -@protocol FLEXFileBrowserFileOperationController - -@property (nonatomic, weak) id delegate; - -- (instancetype)initWithPath:(NSString *)path; - -- (void)show; - -@end - -@interface FLEXFileBrowserFileDeleteOperationController : NSObject -@end - -@interface FLEXFileBrowserFileRenameOperationController : NSObject -@end diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m deleted file mode 100644 index eca19450c7..0000000000 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserFileOperationController.m +++ /dev/null @@ -1,142 +0,0 @@ -// -// FLEXFileBrowserFileOperationController.m -// Flipboard -// -// Created by Daniel Rodriguez Troitino on 2/13/15. -// Copyright (c) 2015 Flipboard. All rights reserved. -// - -#import "FLEXFileBrowserFileOperationController.h" -#import - -@interface FLEXFileBrowserFileDeleteOperationController () - -@property (nonatomic, copy, readonly) NSString *path; - -- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; - -@end - -@implementation FLEXFileBrowserFileDeleteOperationController - -@synthesize delegate = _delegate; - -- (instancetype)init -{ - return [self initWithPath:nil]; -} - -- (instancetype)initWithPath:(NSString *)path -{ - self = [super init]; - if (self) { - _path = path; - } - - return self; -} - -- (void)show -{ - BOOL isDirectory = NO; - BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:&isDirectory]; - - if (stillExists) { - UIAlertView *deleteWarning = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"Delete %@?", self.path.lastPathComponent] - message:[NSString stringWithFormat:@"The %@ will be deleted. This operation cannot be undone", isDirectory ? @"directory" : @"file"] - delegate:self - cancelButtonTitle:@"Cancel" - otherButtonTitles:@"Delete", nil]; - [deleteWarning show]; - } else { - [[[UIAlertView alloc] initWithTitle:@"File Removed" message:@"The file at the specified path no longer exists." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; - } -} - -#pragma mark - UIAlertViewDelegate - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if (buttonIndex == alertView.cancelButtonIndex) { - // Nothing, just cancel - } else if (buttonIndex == alertView.firstOtherButtonIndex) { - [NSFileManager.defaultManager removeItemAtPath:self.path error:NULL]; - } -} - -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex -{ - [self.delegate fileOperationControllerDidDismiss:self]; -} - -@end - -@interface FLEXFileBrowserFileRenameOperationController () - -@property (nonatomic, copy, readonly) NSString *path; - -- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; - -@end - -@implementation FLEXFileBrowserFileRenameOperationController - -@synthesize delegate = _delegate; - -- (instancetype)init -{ - return [self initWithPath:nil]; -} - -- (instancetype)initWithPath:(NSString *)path -{ - self = [super init]; - if (self) { - _path = path; - } - - return self; -} - -- (void)show -{ - BOOL isDirectory = NO; - BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:&isDirectory]; - - if (stillExists) { - UIAlertView *renameDialog = [[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:@"Rename %@?", self.path.lastPathComponent] - message:nil - delegate:self - cancelButtonTitle:@"Cancel" - otherButtonTitles:@"Rename", nil]; - renameDialog.alertViewStyle = UIAlertViewStylePlainTextInput; - UITextField *textField = [renameDialog textFieldAtIndex:0]; - textField.placeholder = @"New file name"; - textField.text = self.path.lastPathComponent; - [renameDialog show]; - } else { - [[[UIAlertView alloc] initWithTitle:@"File Removed" message:@"The file at the specified path no longer exists." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; - } -} - -#pragma mark - UIAlertViewDelegate - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if (buttonIndex == alertView.cancelButtonIndex) { - // Nothing, just cancel - } else if (buttonIndex == alertView.firstOtherButtonIndex) { - NSString *newFileName = [alertView textFieldAtIndex:0].text; - NSString *newPath = [[self.path stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName]; - [NSFileManager.defaultManager moveItemAtPath:self.path toPath:newPath error:NULL]; - } -} - -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex -{ - [self.delegate fileOperationControllerDidDismiss:self]; -} - -@end diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index e0df9efed7..dd5ad36cd6 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -7,7 +7,6 @@ // #import "FLEXFileBrowserTableViewController.h" -#import "FLEXFileBrowserFileOperationController.h" #import "FLEXUtility.h" #import "FLEXWebViewController.h" #import "FLEXImagePreviewViewController.h" @@ -18,7 +17,7 @@ @interface FLEXFileBrowserTableViewCell : UITableViewCell @end -@interface FLEXFileBrowserTableViewController () +@interface FLEXFileBrowserTableViewController () @property (nonatomic, copy) NSString *path; @property (nonatomic, copy) NSArray *childPaths; @@ -27,7 +26,6 @@ @interface FLEXFileBrowserTableViewController () fileOperationController; @end @@ -307,13 +305,6 @@ - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtInd // Since our actions are outside of that protocol, we need to manually handle the action forwarding from the cells. } -#pragma mark - FLEXFileBrowserFileOperationControllerDelegate - -- (void)fileOperationControllerDidDismiss:(id)controller -{ - [self reloadDisplayedPaths]; -} - - (void)openFileController:(NSString *)fullPath { UIDocumentInteractionController *controller = [UIDocumentInteractionController new]; @@ -328,9 +319,27 @@ - (void)fileBrowserRename:(UITableViewCell *)sender NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; NSString *fullPath = [self filePathAtIndexPath:indexPath]; - self.fileOperationController = [[FLEXFileBrowserFileRenameOperationController alloc] initWithPath:fullPath]; - self.fileOperationController.delegate = self; - [self.fileOperationController show]; + BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:NULL]; + if (stillExists) { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Rename %@?", fullPath.lastPathComponent] + message:nil + preferredStyle:UIAlertControllerStyleAlert]; + [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + textField.placeholder = @"New file name"; + textField.text = fullPath.lastPathComponent; + }]; + __weak typeof(alert) weakAlert = alert; + [alert addAction:[UIAlertAction actionWithTitle:@"Rename" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + NSString *newFileName = weakAlert.textFields.firstObject.text; + NSString *newPath = [[fullPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName]; + [NSFileManager.defaultManager moveItemAtPath:fullPath toPath:newPath error:NULL]; + [self reloadDisplayedPaths]; + }]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; + } else { + [FLEXUtility alert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; + } } - (void)fileBrowserDelete:(UITableViewCell *)sender @@ -338,9 +347,21 @@ - (void)fileBrowserDelete:(UITableViewCell *)sender NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; NSString *fullPath = [self filePathAtIndexPath:indexPath]; - self.fileOperationController = [[FLEXFileBrowserFileDeleteOperationController alloc] initWithPath:fullPath]; - self.fileOperationController.delegate = self; - [self.fileOperationController show]; + BOOL isDirectory = NO; + BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:fullPath isDirectory:&isDirectory]; + if (stillExists) { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Delete %@?", fullPath.lastPathComponent] + message:[NSString stringWithFormat:@"The %@ will be deleted. This operation cannot be undone", isDirectory ? @"directory" : @"file"] + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { + [NSFileManager.defaultManager removeItemAtPath:fullPath error:NULL]; + [self reloadDisplayedPaths]; + }]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; + } else { + [FLEXUtility alert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; + } } - (void)fileBrowserCopyPath:(UITableViewCell *)sender diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index a7300f8616..f78fcffd13 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -96,8 +96,6 @@ 3A4C95121B5B21410088C3F2 /* FLEXPropertyEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C948D1B5B21410088C3F2 /* FLEXPropertyEditorViewController.m */; }; 3A4C951E1B5B21410088C3F2 /* FLEXClassesTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C949B1B5B21410088C3F2 /* FLEXClassesTableViewController.h */; settings = {ATTRIBUTES = (Private, ); }; }; 3A4C951F1B5B21410088C3F2 /* FLEXClassesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C949C1B5B21410088C3F2 /* FLEXClassesTableViewController.m */; }; - 3A4C95201B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 3A4C95211B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C949E1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m */; }; 3A4C95221B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C949F1B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 3A4C95231B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94A01B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.m */; }; 3A4C95241B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94A11B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -308,8 +306,6 @@ 3A4C948D1B5B21410088C3F2 /* FLEXPropertyEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXPropertyEditorViewController.m; sourceTree = ""; }; 3A4C949B1B5B21410088C3F2 /* FLEXClassesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassesTableViewController.h; sourceTree = ""; }; 3A4C949C1B5B21410088C3F2 /* FLEXClassesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassesTableViewController.m; sourceTree = ""; }; - 3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserFileOperationController.h; sourceTree = ""; }; - 3A4C949E1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserFileOperationController.m; sourceTree = ""; }; 3A4C949F1B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserSearchOperation.h; sourceTree = ""; }; 3A4C94A01B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserSearchOperation.m; sourceTree = ""; }; 3A4C94A11B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserTableViewController.h; sourceTree = ""; }; @@ -747,8 +743,6 @@ C33CF16B22D664E600F9C6C0 /* FileBrowser */ = { isa = PBXGroup; children = ( - 3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */, - 3A4C949E1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m */, 3A4C949F1B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h */, 3A4C94A01B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.m */, 3A4C94A11B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h */, @@ -859,7 +853,6 @@ 779B1ED21C0C4D7C001F5E49 /* FLEXTableColumnHeader.h in Headers */, 3A4C94FD1B5B21410088C3F2 /* FLEXArgumentInputStructView.h in Headers */, 94A515141C4CA1C00063292F /* FLEXManager.h in Headers */, - 3A4C95201B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h in Headers */, C37A0C93218BAC9600848CA7 /* FLEXObjcInternal.h in Headers */, 3A4C953E1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.h in Headers */, 3A4C95301B5B21410088C3F2 /* FLEXSystemLogMessage.h in Headers */, @@ -1099,7 +1092,6 @@ 3A4C95041B5B21410088C3F2 /* FLEXArgumentInputView.m in Sources */, 3A4C95411B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.m in Sources */, 3A4C94D61B5B21410088C3F2 /* FLEXObjectExplorerViewController.m in Sources */, - 3A4C95211B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m in Sources */, 3A4C94DE1B5B21410088C3F2 /* FLEXHeapEnumerator.m in Sources */, 3A4C95251B5B21410088C3F2 /* FLEXFileBrowserTableViewController.m in Sources */, 3A4C94DA1B5B21410088C3F2 /* FLEXViewControllerExplorerViewController.m in Sources */, From c3066a78477f421b28a9209f78663b7c33bf03ac Mon Sep 17 00:00:00 2001 From: Ryan Olson Date: Sun, 18 Aug 2019 14:59:37 -0700 Subject: [PATCH 23/45] Convert property editor alert view to UIAlertController --- Classes/Editing/FLEXPropertyEditorViewController.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Classes/Editing/FLEXPropertyEditorViewController.m b/Classes/Editing/FLEXPropertyEditorViewController.m index ce65377d86..f6ff104893 100644 --- a/Classes/Editing/FLEXPropertyEditorViewController.m +++ b/Classes/Editing/FLEXPropertyEditorViewController.m @@ -12,6 +12,7 @@ #import "FLEXArgumentInputView.h" #import "FLEXArgumentInputViewFactory.h" #import "FLEXArgumentInputSwitchView.h" +#import "FLEXUtility.h" @interface FLEXPropertyEditorViewController () @@ -62,10 +63,7 @@ - (void)actionButtonPressed:(id)sender NSError *error = nil; [FLEXRuntimeUtility performSelector:setterSelector onObject:self.target withArguments:arguments error:&error]; if (error) { - NSString *title = @"Property Setter Failed"; - NSString *message = [error localizedDescription]; - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alert show]; + [FLEXUtility alert:@"Property Setter Failed" message:[error localizedDescription] from:self]; self.firstInputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target]; } else { // If the setter was called without error, pop the view controller to indicate that and make the user's life easier. From 6cbfa63d48547c76e70ebf156f8a7ea0c0134564 Mon Sep 17 00:00:00 2001 From: Chaoshuai Lu Date: Sun, 18 Aug 2019 15:41:44 -0700 Subject: [PATCH 24/45] Add named struct field parsing support to fix the struct iVar issues --- .../FLEXArgumentInputViewFactory.m | 17 ++-- Classes/Utility/FLEXRuntimeUtility.h | 4 + Classes/Utility/FLEXRuntimeUtility.m | 98 ++++++++++++++----- 3 files changed, 91 insertions(+), 28 deletions(-) diff --git a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.m b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.m index 8b15c77c20..93a46aa70d 100644 --- a/Classes/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.m +++ b/Classes/Editing/ArgumentInputViews/FLEXArgumentInputViewFactory.m @@ -17,6 +17,7 @@ #import "FLEXArgumentInputFontView.h" #import "FLEXArgumentInputColorView.h" #import "FLEXArgumentInputDateView.h" +#import "FLEXRuntimeUtility.h" @implementation FLEXArgumentInputViewFactory @@ -33,11 +34,15 @@ + (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEn // The unsupported view shows "nil" and does not allow user input. subclass = [FLEXArgumentInputNotSupportedView class]; } - return [[subclass alloc] initWithArgumentTypeEncoding:typeEncoding]; + // Remove the field name if there is any (e.g. \"width\"d -> d) + const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:typeEncoding]; + return [[subclass alloc] initWithArgumentTypeEncoding:typeEncoding + fieldNameOffset]; } + (Class)argumentInputViewSubclassForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue { + // Remove the field name if there is any (e.g. \"width\"d -> d) + const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:typeEncoding]; Class argumentInputViewSubclass = nil; NSArray *inputViewClasses = @[[FLEXArgumentInputColorView class], [FLEXArgumentInputFontView class], @@ -47,17 +52,17 @@ + (Class)argumentInputViewSubclassForTypeEncoding:(const char *)typeEncoding cur [FLEXArgumentInputDateView class], [FLEXArgumentInputNumberView class], [FLEXArgumentInputObjectView class]]; - + // Note that order is important here since multiple subclasses may support the same type. // An example is the number subclass and the bool subclass for the type @encode(BOOL). // Both work, but we'd prefer to use the bool subclass. - for (Class inputView in inputViewClasses) { - if ([inputView supportsObjCType:typeEncoding withCurrentValue:currentValue]) { - argumentInputViewSubclass = inputView; + for (Class inputViewClass in inputViewClasses) { + if ([inputViewClass supportsObjCType:typeEncoding + fieldNameOffset withCurrentValue:currentValue]) { + argumentInputViewSubclass = inputViewClass; break; } } - + return argumentInputViewSubclass; } diff --git a/Classes/Utility/FLEXRuntimeUtility.h b/Classes/Utility/FLEXRuntimeUtility.h index 35f77f0a54..293d02d6d7 100644 --- a/Classes/Utility/FLEXRuntimeUtility.h +++ b/Classes/Utility/FLEXRuntimeUtility.h @@ -53,6 +53,7 @@ typedef NS_ENUM(char, FLEXTypeEncoding) FLEXTypeEncodingStructEnd = '}', FLEXTypeEncodingUnionBegin = '(', FLEXTypeEncodingUnionEnd = ')', + FLEXTypeEncodingQuote = '\"', FLEXTypeEncodingBitField = 'b', FLEXTypeEncodingPointer = '^', FLEXTypeEncodingConst = 'r' @@ -67,6 +68,9 @@ typedef NS_ENUM(char, FLEXTypeEncoding) + (BOOL)pointerIsValidObjcObject:(const void *)pointer; /// Unwraps raw pointers to objects stored in NSValue, and re-boxes C strings into NSStrings. + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType; +/// Some fields have a name in their encoded string (e.g. \"width\"d) +/// @return the offset to skip the field name, 0 if there is no name ++ (NSUInteger)fieldNameOffsetForTypeEncoding:(const FLEXTypeEncoding *)typeEncoding; /// @return The class hierarchy for the given object or class, /// from the current class to the root-most class. diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 5ee9d30752..f93c5eaa15 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -88,6 +88,19 @@ + (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXType return returnedObjectOrNil; } ++ (NSUInteger)fieldNameOffsetForTypeEncoding:(const FLEXTypeEncoding *)typeEncoding +{ + NSUInteger beginIndex = 0; + while (typeEncoding[beginIndex] == FLEXTypeEncodingQuote) { + NSUInteger endIndex = beginIndex + 1; + while (typeEncoding[endIndex] != FLEXTypeEncodingQuote) { + ++endIndex; + } + beginIndex = endIndex + 1; + } + return beginIndex; +} + + (NSArray *)classHierarchyOfObject:(id)objectOrClass { NSMutableArray *superClasses = [NSMutableArray new]; @@ -682,10 +695,30 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString // The use of macros here was inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html const char *encodingCString = encodingString.UTF8String; + // Some fields have a name, such as {Size=\"width\"d\"height\"d}, we need to extract the name out and recursive + const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:encodingCString]; + if (fieldNameOffset > 0) { + // According to https://github.com/nygard/class-dump/commit/33fb5ed221810685f57c192e1ce8ab6054949a7c, + // there are some consecutive quoted strings, so use `_` to concatenate the names. + NSString *const fieldNamesString = [encodingString substringWithRange:NSMakeRange(0, fieldNameOffset)]; + NSArray *const fieldNames = [fieldNamesString componentsSeparatedByString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote]]; + NSMutableString *finalFieldNamesString = [NSMutableString string]; + for (NSString *const fieldName in fieldNames) { + if (fieldName.length > 0) { + if (finalFieldNamesString.length > 0) { + [finalFieldNamesString appendString:@"_"]; + } + [finalFieldNamesString appendString:fieldName]; + } + } + NSString *const recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:fieldNameOffset]]; + return [NSString stringWithFormat:@"%@ %@", recursiveType, finalFieldNamesString]; + } + // Objects if (encodingCString[0] == FLEXTypeEncodingObjcObject) { NSString *class = [encodingString substringFromIndex:1]; - class = [class stringByReplacingOccurrencesOfString:@"\"" withString:@""]; + class = [class stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote] withString:@""]; if (class.length == 0 || (class.length == 1 && [class characterAtIndex:0] == FLEXTypeEncodingUnknown)) { class = @"id"; } else { @@ -694,7 +727,29 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString return class; } - // C Types + // Qualifier Prefixes + // Do this first since some of the direct translations (i.e. Method) contain a prefix. +#define RECURSIVE_TRANSLATE(prefix, formatString) \ + if (encodingCString[0] == prefix) { \ + NSString *recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:1]]; \ + return [NSString stringWithFormat:formatString, recursiveType]; \ + } + + // If there's a qualifier prefix on the encoding, translate it and then + // recursively call this method with the rest of the encoding string. + RECURSIVE_TRANSLATE('^', @"%@ *"); + RECURSIVE_TRANSLATE('r', @"const %@"); + RECURSIVE_TRANSLATE('n', @"in %@"); + RECURSIVE_TRANSLATE('N', @"inout %@"); + RECURSIVE_TRANSLATE('o', @"out %@"); + RECURSIVE_TRANSLATE('O', @"bycopy %@"); + RECURSIVE_TRANSLATE('R', @"byref %@"); + RECURSIVE_TRANSLATE('V', @"oneway %@"); + RECURSIVE_TRANSLATE('b', @"bitfield(%@)"); + +#undef RECURSIVE_TRANSLATE + + // C Types #define TRANSLATE(ctype) \ if (strcmp(encodingCString, @encode(ctype)) == 0) { \ return (NSString *)CFSTR(#ctype); \ @@ -746,34 +801,33 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString #undef TRANSLATE - // Qualifier Prefixes - // Do this after the checks above since some of the direct translations (i.e. Method) contain a prefix. -#define RECURSIVE_TRANSLATE(prefix, formatString) \ - if (encodingCString[0] == prefix) { \ - NSString *recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:1]]; \ - return [NSString stringWithFormat:formatString, recursiveType]; \ + // For structs, we only use the name of the structs + if (encodingCString[0] == FLEXTypeEncodingStructBegin) { + const char *equals = strchr(encodingCString, '='); + if (equals) { + const char *nameStart = encodingCString + 1; + // For anonymous structs + if (nameStart[0] == FLEXTypeEncodingUnknown) { + return @"anonymous struct"; + } else { + NSString *const structName = [encodingString substringWithRange:NSMakeRange(nameStart - encodingCString, equals - nameStart)]; + return structName; + } + } } - // If there's a qualifier prefix on the encoding, translate it and then - // recursively call this method with the rest of the encoding string. - RECURSIVE_TRANSLATE('^', @"%@ *"); - RECURSIVE_TRANSLATE('r', @"const %@"); - RECURSIVE_TRANSLATE('n', @"in %@"); - RECURSIVE_TRANSLATE('N', @"inout %@"); - RECURSIVE_TRANSLATE('o', @"out %@"); - RECURSIVE_TRANSLATE('O', @"bycopy %@"); - RECURSIVE_TRANSLATE('R', @"byref %@"); - RECURSIVE_TRANSLATE('V', @"oneway %@"); - RECURSIVE_TRANSLATE('b', @"bitfield(%@)"); - -#undef RECURSIVE_TRANSLATE - // If we couldn't translate, just return the original encoding string return encodingString; } + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type { + // Remove the field name if there is any (e.g. \"width\"d -> d) + const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:type]; + if (fieldNameOffset > 0) { + return [self valueForPrimitivePointer:pointer objCType:type + fieldNameOffset]; + } + // CASE macro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html #define CASE(ctype, selectorpart) \ if (strcmp(type, @encode(ctype)) == 0) { \ From b9c9af5509400181fddfa7213419285d6d9d1c6c Mon Sep 17 00:00:00 2001 From: Iulian Onofrei <6d0847b9@opayq.com> Date: Mon, 19 Aug 2019 23:15:48 +0300 Subject: [PATCH 25/45] Fix explorer not showing up when not specifying a scene --- Classes/Manager/FLEXManager.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index b28731f7f0..5ca03e0570 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -80,8 +80,10 @@ - (void)showExplorer self.explorerWindow.hidden = NO; #if FLEX_AT_LEAST_IOS13_SDK if (@available(iOS 13.0, *)) { - // Only look for a new scene if the one we have isn't the active scene - if (self.explorerWindow.windowScene.activationState != UISceneActivationStateForegroundActive) { + // Only look for a new scene if we don't have one, or the one we have + // isn't the active scene + if (!self.explorerWindow.windowScene || + self.explorerWindow.windowScene.activationState != UISceneActivationStateForegroundActive) { for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { // Look for an active UIWindowScene if (scene.activationState == UISceneActivationStateForegroundActive && From ca919a418830abf86bfc56f1382cab895fc9f88a Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Tue, 20 Aug 2019 16:14:05 -0500 Subject: [PATCH 26/45] Silence deprecation warnings in UICatalog We will rewrite the whole project eventually per #314 --- Example/UICatalog.xcodeproj/project.pbxproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Example/UICatalog.xcodeproj/project.pbxproj b/Example/UICatalog.xcodeproj/project.pbxproj index 5133313fda..37bbd786ae 100644 --- a/Example/UICatalog.xcodeproj/project.pbxproj +++ b/Example/UICatalog.xcodeproj/project.pbxproj @@ -529,6 +529,10 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = ( + "-Wno-deprecated-declarations", + "-Wno-deprecated-implementations", + ); }; name = Debug; }; @@ -576,6 +580,10 @@ SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Wno-deprecated-declarations", + "-Wno-deprecated-implementations", + ); }; name = Release; }; From ac4c50b62cbcbcc1c8ad5f2e664c97830bafecb5 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Tue, 20 Aug 2019 19:07:28 -0500 Subject: [PATCH 27/45] Adopt FLEXAlert - Add FLEXAlert, a builder-oriented UIAlertController wrapper - Replace all uses of UIAlertController with FLEXAlert - Moves some alert methods from FLEXUtility to FLEXAlert --- .../Editing/FLEXMethodCallingViewController.m | 2 +- .../FLEXPropertyEditorViewController.m | 2 +- .../FLEXAddressExplorerCoordinator.m | 52 ++--- .../FLEXFileBrowserTableViewController.m | 59 ++--- .../FLEXSystemLogTableViewController.m | 19 +- .../FLEXNetworkSettingsTableViewController.m | 13 +- ...workTransactionDetailTableViewController.m | 52 +++-- Classes/Utility/FLEXAlert.h | 79 +++++++ Classes/Utility/FLEXAlert.m | 208 ++++++++++++++++++ Classes/Utility/FLEXUtility.h | 3 +- Classes/Utility/FLEXUtility.m | 10 +- FLEX.xcodeproj/project.pbxproj | 8 + 12 files changed, 402 insertions(+), 105 deletions(-) create mode 100644 Classes/Utility/FLEXAlert.h create mode 100644 Classes/Utility/FLEXAlert.m diff --git a/Classes/Editing/FLEXMethodCallingViewController.m b/Classes/Editing/FLEXMethodCallingViewController.m index aa8a1595ce..34bf2909ea 100644 --- a/Classes/Editing/FLEXMethodCallingViewController.m +++ b/Classes/Editing/FLEXMethodCallingViewController.m @@ -95,7 +95,7 @@ - (void)actionButtonPressed:(id)sender id returnedObject = [FLEXRuntimeUtility performSelector:method_getName(self.method) onObject:self.target withArguments:arguments error:&error]; if (error) { - [FLEXUtility alert:@"Method Call Failed" message:[error localizedDescription] from:self]; + [FLEXAlert showAlert:@"Method Call Failed" message:[error localizedDescription] from:self]; } else if (returnedObject) { // For non-nil (or void) return types, push an explorer view controller to display the returned object returnedObject = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnedObject type:self.returnType]; diff --git a/Classes/Editing/FLEXPropertyEditorViewController.m b/Classes/Editing/FLEXPropertyEditorViewController.m index f6ff104893..303d1d8270 100644 --- a/Classes/Editing/FLEXPropertyEditorViewController.m +++ b/Classes/Editing/FLEXPropertyEditorViewController.m @@ -63,7 +63,7 @@ - (void)actionButtonPressed:(id)sender NSError *error = nil; [FLEXRuntimeUtility performSelector:setterSelector onObject:self.target withArguments:arguments error:&error]; if (error) { - [FLEXUtility alert:@"Property Setter Failed" message:[error localizedDescription] from:self]; + [FLEXAlert showAlert:@"Property Setter Failed" message:[error localizedDescription] from:self]; self.firstInputView.inputValue = [FLEXRuntimeUtility valueForProperty:self.property onObject:self.target]; } else { // If the setter was called without error, pop the view controller to indicate that and make the user's life easier. diff --git a/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m b/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m index a439c0c531..796d09d74c 100644 --- a/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m +++ b/Classes/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m @@ -28,40 +28,32 @@ + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { + (FLEXGlobalsTableViewControllerRowAction)globalsEntryRowAction:(FLEXGlobalsRow)row { return ^(FLEXGlobalsTableViewController *host) { + NSString *title = @"Explore Object at Address"; NSString *message = @"Paste a hexadecimal address below, starting with '0x'. " "Use the unsafe option if you need to bypass pointer validation, " "but know that it may crash the app if the address is invalid."; - UIAlertController *addressInput = [UIAlertController alertControllerWithTitle:title - message:message - preferredStyle:UIAlertControllerStyleAlert]; - void (^handler)(UIAlertAction *) = ^(UIAlertAction *action) { - if (action.style == UIAlertActionStyleCancel) { - [host deselectSelectedRow]; return; - } - NSString *address = addressInput.textFields.firstObject.text; - [host tryExploreAddress:address safely:action.style == UIAlertActionStyleDefault]; - }; - [addressInput addTextFieldWithConfigurationHandler:^(UITextField *textField) { - NSString *copied = UIPasteboard.generalPasteboard.string; - textField.placeholder = @"0x00000070deadbeef"; - // Go ahead and paste our clipboard if we have an address copied - if ([copied hasPrefix:@"0x"]) { - textField.text = copied; - [textField selectAll:nil]; - } - }]; - [addressInput addAction:[UIAlertAction actionWithTitle:@"Explore" - style:UIAlertActionStyleDefault - handler:handler]]; - [addressInput addAction:[UIAlertAction actionWithTitle:@"Unsafe Explore" - style:UIAlertActionStyleDestructive - handler:handler]]; - [addressInput addAction:[UIAlertAction actionWithTitle:@"Cancel" - style:UIAlertActionStyleCancel - handler:handler]]; - [host presentViewController:addressInput animated:YES completion:nil]; + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(title).message(message); + make.configuredTextField(^(UITextField *textField) { + NSString *copied = UIPasteboard.generalPasteboard.string; + textField.placeholder = @"0x00000070deadbeef"; + // Go ahead and paste our clipboard if we have an address copied + if ([copied hasPrefix:@"0x"]) { + textField.text = copied; + [textField selectAll:nil]; + } + }); + make.button(@"Explore").handler(^(NSArray *strings) { + [host tryExploreAddress:strings.firstObject safely:YES]; + }); + make.button(@"Unsafe Explore").destructiveStyle().handler(^(NSArray *strings) { + [host tryExploreAddress:strings.firstObject safely:NO]; + }); + make.button(@"Cancel").cancelStyle(); + } showFrom:host]; + }; } @@ -95,7 +87,7 @@ - (void)tryExploreAddress:(NSString *)addressString safely:(BOOL)safely { FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:object]; [self.navigationController pushViewController:explorer animated:YES]; } else { - [FLEXUtility alert:@"Uh-oh" message:error from:self]; + [FLEXAlert showAlert:@"Uh-oh" message:error from:self]; [self deselectSelectedRow]; } } diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index dd5ad36cd6..e074cca948 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -210,7 +210,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath UIImage *image = cell.imageView.image; if (!stillExists) { - [FLEXUtility alert:@"File Not Found" message:@"The file at the specified path no longer exists." from:self]; + [FLEXAlert showAlert:@"File Not Found" message:@"The file at the specified path no longer exists." from:self]; [self reloadDisplayedPaths]; return; } @@ -223,7 +223,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } else { NSData *fileData = [NSData dataWithContentsOfFile:fullPath]; if (!fileData.length) { - [FLEXUtility alert:@"Empty File" message:@"No data returned from the file." from:self]; + [FLEXAlert showAlert:@"Empty File" message:@"No data returned from the file." from:self]; return; } @@ -321,24 +321,22 @@ - (void)fileBrowserRename:(UITableViewCell *)sender BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:NULL]; if (stillExists) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Rename %@?", fullPath.lastPathComponent] - message:nil - preferredStyle:UIAlertControllerStyleAlert]; - [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { - textField.placeholder = @"New file name"; - textField.text = fullPath.lastPathComponent; - }]; - __weak typeof(alert) weakAlert = alert; - [alert addAction:[UIAlertAction actionWithTitle:@"Rename" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - NSString *newFileName = weakAlert.textFields.firstObject.text; - NSString *newPath = [[fullPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName]; - [NSFileManager.defaultManager moveItemAtPath:fullPath toPath:newPath error:NULL]; - [self reloadDisplayedPaths]; - }]]; - [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; - [self presentViewController:alert animated:YES completion:nil]; + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title([NSString stringWithFormat:@"Rename %@?", fullPath.lastPathComponent]); + make.configuredTextField(^(UITextField *textField) { + textField.placeholder = @"New file name"; + textField.text = fullPath.lastPathComponent; + }); + make.button(@"Rename").handler(^(NSArray *strings) { + NSString *newFileName = strings.firstObject; + NSString *newPath = [fullPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:newFileName]; + [NSFileManager.defaultManager moveItemAtPath:fullPath toPath:newPath error:NULL]; + [self reloadDisplayedPaths]; + }); + make.button(@"Cancel").cancelStyle(); + } showFrom:self]; } else { - [FLEXUtility alert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; + [FLEXAlert showAlert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; } } @@ -350,17 +348,20 @@ - (void)fileBrowserDelete:(UITableViewCell *)sender BOOL isDirectory = NO; BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:fullPath isDirectory:&isDirectory]; if (stillExists) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Delete %@?", fullPath.lastPathComponent] - message:[NSString stringWithFormat:@"The %@ will be deleted. This operation cannot be undone", isDirectory ? @"directory" : @"file"] - preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { - [NSFileManager.defaultManager removeItemAtPath:fullPath error:NULL]; - [self reloadDisplayedPaths]; - }]]; - [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; - [self presentViewController:alert animated:YES completion:nil]; + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Confirm Deletion"); + make.message([NSString stringWithFormat: + @"The %@ '%@' will be deleted. This operation cannot be undone", + (isDirectory ? @"directory" : @"file"), fullPath.lastPathComponent + ]); + make.button(@"Delete").destructiveStyle().handler(^(NSArray *strings) { + [NSFileManager.defaultManager removeItemAtPath:fullPath error:NULL]; + [self reloadDisplayedPaths]; + }); + make.button(@"Cancel").cancelStyle(); + } showFrom:self]; } else { - [FLEXUtility alert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; + [FLEXAlert showAlert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; } } diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m index 06719d57e6..3f4a6918fa 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXSystemLogTableViewController.m @@ -104,16 +104,15 @@ - (void)showLogSettings NSString *body = @"In iOS 10 and up, ASL is gone. The OS Log API is much more limited. " "To get as close to the old behavior as possible, logs must be collected manually at launch and stored.\n\n" "Turn this feature on only when you need it."; - - UIAlertController *settings = [UIAlertController alertControllerWithTitle:title message:body preferredStyle:UIAlertControllerStyleAlert]; - [settings addAction:[UIAlertAction actionWithTitle:toggle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - [[NSUserDefaults standardUserDefaults] setBool:!persistent forKey:kFLEXiOSPersistentOSLogKey]; - logController.persistent = !persistent; - [logController.messages addObjectsFromArray:self.logMessages]; - }]]; - [settings addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:nil]]; - - [self presentViewController:settings animated:YES completion:nil]; + + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(title).message(body).button(toggle).handler(^(NSArray *strings) { + [[NSUserDefaults standardUserDefaults] setBool:!persistent forKey:kFLEXiOSPersistentOSLogKey]; + logController.persistent = !persistent; + [logController.messages addObjectsFromArray:self.logMessages]; + }); + make.button(@"Dismiss").cancelStyle(); + } showFrom:self]; } #pragma mark - FLEXGlobalsEntry diff --git a/Classes/Network/FLEXNetworkSettingsTableViewController.m b/Classes/Network/FLEXNetworkSettingsTableViewController.m index 9cfa6829e3..89ec710e5a 100644 --- a/Classes/Network/FLEXNetworkSettingsTableViewController.m +++ b/Classes/Network/FLEXNetworkSettingsTableViewController.m @@ -74,14 +74,15 @@ - (void)cacheLimitAdjusted:(UISlider *)sender - (void)clearRequestsTapped:(UIButton *)sender { - UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; - [actionSheet addAction:[UIAlertAction actionWithTitle:@"Clear Recorded Requests" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { - [[FLEXNetworkRecorder defaultRecorder] clearRecordedActivity]; - }]]; + [FLEXAlert makeSheet:^(FLEXAlert *make) { + make.button(@"Cancel").cancelStyle(); + make.button(@"Clear Recorded Requests").destructiveStyle().handler(^(NSArray *strings) { + [[FLEXNetworkRecorder defaultRecorder] clearRecordedActivity]; + }); + } showFrom:self]; + self.popoverPresentationController.sourceView = sender; self.popoverPresentationController.sourceRect = sender.bounds; - [self presentViewController:actionSheet animated:YES completion:nil]; } #pragma mark - Table view data source diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m index c051ef9418..c782132f6a 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m @@ -259,7 +259,8 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti FLEXNetworkDetailRow *postBodyRow = [FLEXNetworkDetailRow new]; postBodyRow.title = @"Request Body"; postBodyRow.detailText = @"tap to view"; - postBodyRow.selectionFuture = ^UIViewController * (void){ + postBodyRow.selectionFuture = ^UIViewController * () { + // Show the body if we can NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; UIViewController *detailViewController = [self detailViewControllerForMIMEType:contentType data:[self postBodyDataForTransaction:transaction]]; if (detailViewController) { @@ -267,13 +268,15 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti return detailViewController; } - NSString *alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for request body data with MIME type: %@", [transaction.request valueForHTTPHeaderField:@"Content-Type"]]; - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Can't View Body Data" - message:alertMessage - preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; - return alert; + // We can't show the body, alert user + return [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Can't View HTTP Body Data"); + make.message(@"FLEX does not have a viewer for request body data with MIME type: "); + make.message(contentType); + make.button(@"Dismiss").cancelStyle(); + }]; }; + [rows addObject:postBodyRow]; } @@ -297,33 +300,38 @@ + (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXNetworkTransacti NSData *responseData = [[FLEXNetworkRecorder defaultRecorder] cachedResponseBodyForTransaction:transaction]; if (responseData.length > 0) { responseBodyRow.detailText = @"tap to view"; + // Avoid a long lived strong reference to the response data in case we need to purge it from the cache. __weak NSData *weakResponseData = responseData; - responseBodyRow.selectionFuture = ^UIViewController * (void){ - NSString *alertMessage = nil; + responseBodyRow.selectionFuture = ^UIViewController * () { + + // Show the response if we can + NSString *contentType = transaction.response.MIMEType; NSData *strongResponseData = weakResponseData; if (strongResponseData) { - UIViewController *responseBodyDetailViewController = [self detailViewControllerForMIMEType:transaction.response.MIMEType data:strongResponseData]; - if (responseBodyDetailViewController) { - responseBodyDetailViewController.title = @"Response"; - return responseBodyDetailViewController; + UIViewController *bodyDetailController = [self detailViewControllerForMIMEType:contentType data:strongResponseData]; + if (bodyDetailController) { + bodyDetailController.title = @"Response"; + return bodyDetailController; } - - alertMessage = [NSString stringWithFormat:@"FLEX does not have a viewer for responses with MIME type: %@", transaction.response.MIMEType]; - } else { - alertMessage = @"The response has been purged from the cache"; } - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Can't View Response" - message:alertMessage - preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; - return alert; + // We can't show the response, alert user + return [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Unable to View Response"); + if (strongResponseData) { + make.message(@"No viewer content type: ").message(contentType); + } else { + make.message(@"The response has been purged from the cache"); + } + make.button(@"OK").cancelStyle(); + }]; }; } else { BOOL emptyResponse = transaction.receivedDataLength == 0; responseBodyRow.detailText = emptyResponse ? @"empty" : @"not in cache"; } + [rows addObject:responseBodyRow]; FLEXNetworkDetailRow *responseSizeRow = [FLEXNetworkDetailRow new]; diff --git a/Classes/Utility/FLEXAlert.h b/Classes/Utility/FLEXAlert.h new file mode 100644 index 0000000000..fd38704510 --- /dev/null +++ b/Classes/Utility/FLEXAlert.h @@ -0,0 +1,79 @@ +// +// FLEXAlert.h +// FLEX +// +// Created by Tanner Bennett on 8/20/19. +// Copyright © 2019 Flipboard. All rights reserved. +// + +#import + +@class FLEXAlert, FLEXAlertAction; + +typedef void (^FLEXAlertReveal)(); +typedef void (^FLEXAlertBuilder)(FLEXAlert *make); +typedef FLEXAlert *(^FLEXAlertStringProperty)(NSString *); +typedef FLEXAlert *(^FLEXAlertStringArg)(NSString *); +typedef FLEXAlert *(^FLEXAlertTextField)(void(^configurationHandler)(UITextField *textField)); +typedef FLEXAlertAction *(^FLEXAlertAddAction)(NSString *title); +typedef FLEXAlertAction *(^FLEXAlertActionStringProperty)(NSString *); +typedef FLEXAlertAction *(^FLEXAlertActionProperty)(); +typedef FLEXAlertAction *(^FLEXAlertActionBOOLProperty)(BOOL); +typedef FLEXAlertAction *(^FLEXAlertActionHandler)(void(^handler)(NSArray *strings)); + +@interface FLEXAlert : NSObject + +/// Shows a simple alert with one button which says "Dismiss" ++ (void)showAlert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController; + +/// Construct and display an alert ++ (void)makeAlert:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController; +/// Construct and display an action sheet-style alert ++ (void)makeSheet:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController; + +/// Construct an alert ++ (UIAlertController *)makeAlert:(FLEXAlertBuilder)block; +/// Construct an action sheet-style alert ++ (UIAlertController *)makeSheet:(FLEXAlertBuilder)block; + +/// Set the alert's title. +/// +/// Call in succession to append strings to the title. +@property (nonatomic, readonly) FLEXAlertStringProperty title; +/// Set the alert's message. +/// +/// Call in succession to append strings to the message. +@property (nonatomic, readonly) FLEXAlertStringProperty message; +/// Add a button with a given title with the default style and no action. +@property (nonatomic, readonly) FLEXAlertAddAction button; +/// Add a text field with the given (optional) placeholder text. +@property (nonatomic, readonly) FLEXAlertStringArg textField; +/// Add and configure the given text field. +/// +/// Use this if you need to more than set the placeholder, such as +/// supply a delegate, make it secure entry, or change other attributes. +@property (nonatomic, readonly) FLEXAlertTextField configuredTextField; + +@end + +@interface FLEXAlertAction : NSObject + +/// Set the action's title. +/// +/// Call in succession to append strings to the title. +@property (nonatomic, readonly) FLEXAlertActionStringProperty title; +/// Make the action destructive. It appears with red text. +@property (nonatomic, readonly) FLEXAlertActionProperty destructiveStyle; +/// Make the action cancel-style. It appears with a bolder font. +@property (nonatomic, readonly) FLEXAlertActionProperty cancelStyle; +/// Enable or disable the action. Enabled by default. +@property (nonatomic, readonly) FLEXAlertActionBOOLProperty enabled; +/// Give the button an action. The action takes an array of text field strings. +@property (nonatomic, readonly) FLEXAlertActionHandler handler; +/// Access the underlying UIAlertAction, should you need to change it while +/// the encompassing alert is being displayed. For example, you may want to +/// enable or disable a button based on the input of some text fields in the alert. +/// Do not call this more than once per instance. +@property (nonatomic, readonly) UIAlertAction *action; + +@end diff --git a/Classes/Utility/FLEXAlert.m b/Classes/Utility/FLEXAlert.m new file mode 100644 index 0000000000..3eaa8c315b --- /dev/null +++ b/Classes/Utility/FLEXAlert.m @@ -0,0 +1,208 @@ +// +// FLEXAlert.m +// FLEX +// +// Created by Tanner Bennett on 8/20/19. +// Copyright © 2019 Flipboard. All rights reserved. +// + +#import "FLEXAlert.h" + +@interface FLEXAlert () +@property (nonatomic, readonly) UIAlertController *_controller; +@property (nonatomic, readonly) NSMutableArray *_actions; +@end + +#define FLEXAlertActionMutationAssertion() \ +NSAssert(!self._action, @"Cannot mutate action after retreiving underlying UIAlertAction"); + +@interface FLEXAlertAction () +@property (nonatomic) UIAlertController *_controller; +@property (nonatomic) NSString *_title; +@property (nonatomic) UIAlertActionStyle _style; +@property (nonatomic) BOOL _disable; +@property (nonatomic) void(^_handler)(UIAlertAction *action); +@property (nonatomic) UIAlertAction *_action; +@end + +@implementation FLEXAlert + ++ (void)showAlert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController { + [self makeAlert:^(FLEXAlert *make) { + make.title(title).message(message).button(@"Dismiss").cancelStyle(); + } showFrom:viewController]; +} + +#pragma mark Initialization + +- (instancetype)initWithController:(UIAlertController *)controller { + self = [super init]; + if (self) { + __controller = controller; + __actions = [NSMutableArray new]; + } + + return self; +} + ++ (UIAlertController *)make:(FLEXAlertBuilder)block withStyle:(UIAlertControllerStyle)style { + // Create alert builder + FLEXAlert *alert = [[self alloc] initWithController: + [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style] + ]; + + // Configure alert + block(alert); + + // Add actions + for (FLEXAlertAction *builder in alert._actions) { + [alert._controller addAction:builder.action]; + } + + return alert._controller; +} + ++ (void)make:(FLEXAlertBuilder)block withStyle:(UIAlertControllerStyle)style showFrom:(UIViewController *)viewController { + UIAlertController *alert = [self make:block withStyle:style]; + [viewController presentViewController:alert animated:YES completion:nil]; +} + ++ (void)makeAlert:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController { + [self make:block withStyle:UIAlertControllerStyleAlert showFrom:viewController]; +} + ++ (void)makeSheet:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController { + [self make:block withStyle:UIAlertControllerStyleActionSheet showFrom:viewController]; +} + ++ (UIAlertController *)makeAlert:(FLEXAlertBuilder)block { + return [self make:block withStyle:UIAlertControllerStyleAlert]; +} + ++ (UIAlertController *)makeSheet:(FLEXAlertBuilder)block { + return [self make:block withStyle:UIAlertControllerStyleActionSheet]; +} + +#pragma mark Configuration + +- (FLEXAlertStringProperty)title { + return ^FLEXAlert *(NSString *title) { + if (self._controller.title) { + self._controller.title = [self._controller.title stringByAppendingString:title]; + } else { + self._controller.title = title; + } + return self; + }; +} + +- (FLEXAlertStringProperty)message { + return ^FLEXAlert *(NSString *message) { + if (self._controller.message) { + self._controller.message = [self._controller.message stringByAppendingString:message]; + } else { + self._controller.message = message; + } + return self; + }; +} + +- (FLEXAlertAddAction)button { + return ^FLEXAlertAction *(NSString *title) { + FLEXAlertAction *action = FLEXAlertAction.new.title(title); + action._controller = self._controller; + [self._actions addObject:action]; + return action; + }; +} + +- (FLEXAlertStringArg)textField { + return ^FLEXAlert *(NSString *placeholder) { + [self._controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.placeholder = placeholder; + }]; + + return self; + }; +} + +- (FLEXAlertTextField)configuredTextField { + return ^FLEXAlert *(void(^configurationHandler)(UITextField *)) { + [self._controller addTextFieldWithConfigurationHandler:configurationHandler]; + return self; + }; +} + +@end + +@implementation FLEXAlertAction + +- (FLEXAlertActionStringProperty)title { + return ^FLEXAlertAction *(NSString *title) { + FLEXAlertActionMutationAssertion(); + if (self._title) { + self._title = [self._title stringByAppendingString:title]; + } else { + self._title = title; + } + return self; + }; +} + +- (FLEXAlertActionProperty)destructiveStyle { + return ^FLEXAlertAction *() { + FLEXAlertActionMutationAssertion(); + self._style = UIAlertActionStyleDestructive; + return self; + }; +} + +- (FLEXAlertActionProperty)cancelStyle { + return ^FLEXAlertAction *() { + FLEXAlertActionMutationAssertion(); + self._style = UIAlertActionStyleCancel; + return self; + }; +} + +- (FLEXAlertActionBOOLProperty)enabled { + return ^FLEXAlertAction *(BOOL enabled) { + FLEXAlertActionMutationAssertion(); + self._disable = !enabled; + return self; + }; +} + +- (FLEXAlertActionHandler)handler { + return ^FLEXAlertAction *(void(^handler)(NSArray *)) { + FLEXAlertActionMutationAssertion(); + + // Get weak reference to the alert to avoid block <--> alert retain cycle + __weak __typeof(self._controller) weakController = self._controller; + self._handler = ^(UIAlertAction *action) { + // Strongify that reference and pass the text field strings to the handler + __strong __typeof(weakController) controller = weakController; + NSArray *strings = [controller.textFields valueForKeyPath:@"text"]; + handler(strings); + }; + + return self; + }; +} + +- (UIAlertAction *)action { + if (self._action) { + return self._action; + } + + self._action = [UIAlertAction + actionWithTitle:self._title + style:self._style + handler:self._handler + ]; + self._action.enabled = !self._disable; + + return self._action; +} + +@end diff --git a/Classes/Utility/FLEXUtility.h b/Classes/Utility/FLEXUtility.h index c8035ff92c..1f2cdb0b9e 100644 --- a/Classes/Utility/FLEXUtility.h +++ b/Classes/Utility/FLEXUtility.h @@ -11,6 +11,7 @@ #import #import #import +#import "FLEXAlert.h" #define FLEXFloor(x) (floor(UIScreen.mainScreen.scale * (x)) / UIScreen.mainScreen.scale) @@ -54,8 +55,6 @@ + (NSArray *)allWindows; -+ (void)alert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController; - // Swizzling utilities + (SEL)swizzledSelectorForSelector:(SEL)selector; diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index b5b187c4c7..93bc1a525c 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -411,11 +411,13 @@ + (NSArray *)map:(NSArray *)array block:(id(^)(id obj, NSUInteger idx))mapFunc return windows; } -+ (void)alert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController ++ (UIAlertController *)alert:(NSString *)title message:(NSString *)message { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleDefault handler:nil]]; - [viewController presentViewController:alert animated:YES completion:nil]; + return [UIAlertController + alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert + ]; } + (SEL)swizzledSelectorForSelector:(SEL)selector diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index f78fcffd13..79e2e1df6b 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -182,6 +182,8 @@ C387C88422E0D24A00750E58 /* UIView+Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = C387C88222E0D24A00750E58 /* UIView+Layout.m */; }; C38DF0EA22CFE4370077B4AD /* FLEXTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */; }; C38DF0EB22CFE4370077B4AD /* FLEXTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */; }; + C38F3F31230C958F004E3731 /* FLEXAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = C38F3F2F230C958F004E3731 /* FLEXAlert.h */; }; + C38F3F32230C958F004E3731 /* FLEXAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F3F30230C958F004E3731 /* FLEXAlert.m */; }; C395D6D921789BD800BEAD4D /* FLEXColorExplorerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C395D6D721789BD800BEAD4D /* FLEXColorExplorerViewController.h */; }; C395D6DA21789BD800BEAD4D /* FLEXColorExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C395D6D821789BD800BEAD4D /* FLEXColorExplorerViewController.m */; }; C39ED92822D63F3200B5773A /* FLEXAddressExplorerCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = C39ED92622D63F3200B5773A /* FLEXAddressExplorerCoordinator.h */; }; @@ -395,6 +397,8 @@ C387C88222E0D24A00750E58 /* UIView+Layout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+Layout.m"; sourceTree = ""; }; C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewController.h; sourceTree = ""; }; C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewController.m; sourceTree = ""; }; + C38F3F2F230C958F004E3731 /* FLEXAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXAlert.h; sourceTree = ""; }; + C38F3F30230C958F004E3731 /* FLEXAlert.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXAlert.m; sourceTree = ""; }; C395D6D721789BD800BEAD4D /* FLEXColorExplorerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXColorExplorerViewController.h; sourceTree = ""; }; C395D6D821789BD800BEAD4D /* FLEXColorExplorerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXColorExplorerViewController.m; sourceTree = ""; }; C39ED92622D63F3200B5773A /* FLEXAddressExplorerCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXAddressExplorerCoordinator.h; sourceTree = ""; }; @@ -518,6 +522,8 @@ 3A4C945C1B5B21410088C3F2 /* FLEXRuntimeUtility.m */, 3A4C945D1B5B21410088C3F2 /* FLEXUtility.h */, 3A4C945E1B5B21410088C3F2 /* FLEXUtility.m */, + C38F3F2F230C958F004E3731 /* FLEXAlert.h */, + C38F3F30230C958F004E3731 /* FLEXAlert.m */, 942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */, 942DCD831BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.m */, 94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */, @@ -845,6 +851,7 @@ 3A4C94ED1B5B21410088C3F2 /* FLEXArgumentInputColorView.h in Headers */, 3A4C94EB1B5B21410088C3F2 /* FLEXImagePreviewViewController.h in Headers */, C3DA55FE21A76406005DDA60 /* FLEXMutableFieldEditorViewController.h in Headers */, + C38F3F31230C958F004E3731 /* FLEXAlert.h in Headers */, 3A4C95381B5B21410088C3F2 /* FLEXNetworkRecorder.h in Headers */, 3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */, 3A4C95051B5B21410088C3F2 /* FLEXArgumentInputViewFactory.h in Headers */, @@ -1067,6 +1074,7 @@ 94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */, 3A4C951F1B5B21410088C3F2 /* FLEXClassesTableViewController.m in Sources */, 3A4C94C61B5B21410088C3F2 /* FLEXArrayExplorerViewController.m in Sources */, + C38F3F32230C958F004E3731 /* FLEXAlert.m in Sources */, C3DA55FF21A76406005DDA60 /* FLEXMutableFieldEditorViewController.m in Sources */, 3A4C95081B5B21410088C3F2 /* FLEXDefaultEditorViewController.m in Sources */, 779B1ED11C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m in Sources */, From a21e5ea158a8662e2cf6b22c183af7e353c16a8d Mon Sep 17 00:00:00 2001 From: ray Date: Sat, 17 Aug 2019 17:10:21 +0800 Subject: [PATCH 28/45] Initial support for viewing keychain items --- .../Globals/FLEXGlobalsEntry.h | 1 + .../Globals/FLEXGlobalsTableViewController.m | 4 + .../FLEXKeyChainTableViewController.h | 18 + .../FLEXKeyChainTableViewController.m | 137 ++++++++ .../KeyChain/FLEXKeychain.h | 198 +++++++++++ .../KeyChain/FLEXKeychain.m | 130 +++++++ .../KeyChain/FLEXKeychainQuery.h | 143 ++++++++ .../KeyChain/FLEXKeychainQuery.m | 316 ++++++++++++++++++ FLEX.podspec | 2 +- FLEX.xcodeproj/project.pbxproj | 32 ++ 10 files changed, 980 insertions(+), 1 deletion(-) create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h create mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h index 2ac22e175a..727e73c6ea 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h @@ -19,6 +19,7 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) { FLEXGlobalsRowCookies, FLEXGlobalsRowSystemLibraries, FLEXGlobalsRowAppClasses, + FLEXGlobalsRowAppKeyChainItems, FLEXGlobalsRowAppDelegate, FLEXGlobalsRowRootViewController, FLEXGlobalsRowUserDefaults, diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m index d436afb93a..2f586c6952 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m @@ -11,6 +11,7 @@ #import "FLEXRuntimeUtility.h" #import "FLEXLibrariesTableViewController.h" #import "FLEXClassesTableViewController.h" +#import "FLEXKeyChainTableViewController.h" #import "FLEXObjectExplorerViewController.h" #import "FLEXObjectExplorerFactory.h" #import "FLEXLiveObjectsTableViewController.h" @@ -56,6 +57,8 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row switch (row) { case FLEXGlobalsRowAppClasses: return [FLEXClassesTableViewController flex_concreteGlobalsEntry:row]; + case FLEXGlobalsRowAppKeyChainItems: + return [FLEXKeyChainTableViewController flex_concreteGlobalsEntry:row]; case FLEXGlobalsRowAddressInspector: return [FLEXAddressExplorerCoordinator flex_concreteGlobalsEntry:row]; case FLEXGlobalsRowSystemLibraries: @@ -121,6 +124,7 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row @[ // FLEXGlobalsSectionAppShortcuts [self globalsEntryForRow:FLEXGlobalsRowMainBundle], [self globalsEntryForRow:FLEXGlobalsRowUserDefaults], + [self globalsEntryForRow:FLEXGlobalsRowAppKeyChainItems], [self globalsEntryForRow:FLEXGlobalsRowApplication], [self globalsEntryForRow:FLEXGlobalsRowAppDelegate], [self globalsEntryForRow:FLEXGlobalsRowKeyWindow], diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h b/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h new file mode 100644 index 0000000000..88844a4822 --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h @@ -0,0 +1,18 @@ +// +// FLEXKeyChainTableViewController.h +// FLEX +// +// Created by ray on 2019/8/17. +// Copyright © 2019 Flipboard. All rights reserved. +// + +#import "FLEXGlobalsEntry.h" +#import "FLEXTableViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FLEXKeyChainTableViewController : FLEXTableViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m b/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m new file mode 100644 index 0000000000..3889fa83fc --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m @@ -0,0 +1,137 @@ +// +// FLEXKeyChainTableViewController.m +// FLEX +// +// Created by ray on 2019/8/17. +// Copyright © 2019 Flipboard. All rights reserved. +// + +#import "FLEXKeychain.h" +#import "FLEXKeychainQuery.h" +#import "FLEXKeyChainTableViewController.h" +#import "FLEXUtility.h" + +@interface FLEXKeyChainTableViewController () + +@property (nonatomic) NSArray *keyChainItems; + +@end + +@implementation FLEXKeyChainTableViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(clearKeyChain)]; + + + _keyChainItems = [FLEXKeychain allAccounts]; + self.title = [NSString stringWithFormat:@"🔑 KeyChains (%lu)", (unsigned long)self.keyChainItems.count]; +} + +- (void)clearKeyChain +{ + + for (id account in _keyChainItems) { + + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + + query.service = [account valueForKey:kSSKeychainWhereKey]; + query.account = [account valueForKey:kSSKeychainAccountKey]; + + if(![query deleteItem:nil]) { + NSLog(@"Delete Keychin Item Failed."); + } + } + + _keyChainItems = [FLEXKeychain allAccounts]; + [self.tableView reloadData]; +} + +#pragma mark - FLEXGlobalsEntry + ++ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row +{ + return [NSString stringWithFormat:@"🔑 %@ KeyChain", [FLEXUtility applicationName]]; +} + ++ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row +{ + FLEXKeyChainTableViewController *keyChainViewController = [self new]; + + return keyChainViewController; +} + + +#pragma mark - Table View Data Source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return self.keyChainItems.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + static NSString *CellIdentifier = @"Cell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont]; + } + + NSDictionary *item = self.keyChainItems[indexPath.row]; + cell.textLabel.text = item[kSSKeychainAccountKey]; + + return cell; +} + + +#pragma mark - Table View Delegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSDictionary *item = self.keyChainItems[indexPath.row]; + + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = [item valueForKey:kSSKeychainWhereKey]; + query.account = [item valueForKey:kSSKeychainAccountKey]; + [query fetch:nil]; + + NSString *msg = nil; + + if ([query.password length]) + { + msg = query.password; + } + + else if ([query.passwordData length]) + { + msg = [query.passwordData description]; + } + + else + { + msg = @"NO Data!"; + } + + UIAlertController *cv = [UIAlertController alertControllerWithTitle:@"Password" message:msg preferredStyle:UIAlertControllerStyleAlert]; + [cv addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [cv dismissViewControllerAnimated:YES completion:nil]; + }]]; + + [cv addAction:[UIAlertAction actionWithTitle:@"Copy" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + pasteboard.string = msg; + }]]; + + [self presentViewController:cv animated:YES completion:nil]; +} + +@end diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h new file mode 100644 index 0000000000..47e9adb45d --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h @@ -0,0 +1,198 @@ +// +// SSKeychain.h +// SSKeychain +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#if __has_feature(modules) + @import Foundation; +#else + #import +#endif + +/** + Error code specific to SSKeychain that can be returned in NSError objects. + For codes returned by the operating system, refer to SecBase.h for your + platform. + */ +typedef NS_ENUM(OSStatus, SSKeychainErrorCode) { + /** Some of the arguments were invalid. */ + SSKeychainErrorBadArguments = -1001, +}; + +/** SSKeychain error domain */ +extern NSString *const kSSKeychainErrorDomain; + +/** Account name. */ +extern NSString *const kSSKeychainAccountKey; + +/** + Time the item was created. + + The value will be a string. + */ +extern NSString *const kSSKeychainCreatedAtKey; + +/** Item class. */ +extern NSString *const kSSKeychainClassKey; + +/** Item description. */ +extern NSString *const kSSKeychainDescriptionKey; + +/** Item label. */ +extern NSString *const kSSKeychainLabelKey; + +/** Time the item was last modified. + + The value will be a string. + */ +extern NSString *const kSSKeychainLastModifiedKey; + +/** Where the item was created. */ +extern NSString *const kSSKeychainWhereKey; + +/** + Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system + Keychain on Mac OS X and iOS. + + This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. + SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it). + */ +@interface FLEXKeychain : NSObject + +#pragma mark - Classic methods + +/** + Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + */ ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @return Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + */ ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + + +/** + Deletes a password from the Keychain. + + @param serviceName The service for which to delete the corresponding password. + + @param account The account for which to delete the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. The order of the objects in the array isn't defined. + */ ++ (NSArray *> *)allAccounts; ++ (NSArray *> *)allAccounts:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); + + +/** + Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any + accounts for the given service. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @param serviceName The service for which to return the corresponding accounts. + + @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, or `nil` if the Keychain + doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. + */ ++ (NSArray *> *)accountsForService:(NSString *)serviceName; ++ (NSArray *> *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); + + +#pragma mark - Configuration + +#if __IPHONE_4_0 && TARGET_OS_IPHONE +/** + Returns the accessibility type for all future passwords saved to the Keychain. + + @return Returns the accessibility type. + + The return value will be `NULL` or one of the "Keychain Item Accessibility + Constants" used for determining when a keychain item should be readable. + + @see setAccessibilityType + */ ++ (CFTypeRef)accessibilityType; + +/** + Sets the accessibility type for all future passwords saved to the Keychain. + + @param accessibilityType One of the "Keychain Item Accessibility Constants" + used for determining when a keychain item should be readable. + + If the value is `NULL` (the default), the Keychain default will be used which + is highly insecure. You really should use at least `kSecAttrAccessibleAfterFirstUnlock` + for background applications or `kSecAttrAccessibleWhenUnlocked` for all + other applications. + + @see accessibilityType + */ ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType; +#endif + +@end + diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m new file mode 100644 index 0000000000..f44042314a --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m @@ -0,0 +1,130 @@ +// +// SSKeychain.m +// SSKeychain +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#import "FLEXKeychain.h" +#import "FLEXKeychainQuery.h" + +NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain"; +NSString *const kSSKeychainAccountKey = @"acct"; +NSString *const kSSKeychainCreatedAtKey = @"cdat"; +NSString *const kSSKeychainClassKey = @"labl"; +NSString *const kSSKeychainDescriptionKey = @"desc"; +NSString *const kSSKeychainLabelKey = @"labl"; +NSString *const kSSKeychainLastModifiedKey = @"mdat"; +NSString *const kSSKeychainWhereKey = @"svce"; + +#if __IPHONE_4_0 && TARGET_OS_IPHONE + static CFTypeRef SSKeychainAccessibilityType = NULL; +#endif + +@implementation FLEXKeychain + ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { + return [self passwordForService:serviceName account:account error:nil]; +} + + ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + return query.password; +} + ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account { + return [self passwordDataForService:serviceName account:account error:nil]; +} + ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + + return query.passwordData; +} + + ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account { + return [self deletePasswordForService:serviceName account:account error:nil]; +} + + ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + return [query deleteItem:error]; +} + + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { + return [self setPassword:password forService:serviceName account:account error:nil]; +} + + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + query.password = password; + return [query save:error]; +} + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account { + return [self setPasswordData:password forService:serviceName account:account error:nil]; +} + + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + query.passwordData = password; + return [query save:error]; +} + ++ (NSArray *)allAccounts { + return [self allAccounts:nil]; +} + + ++ (NSArray *)allAccounts:(NSError *__autoreleasing *)error { + return [self accountsForService:nil error:error]; +} + + ++ (NSArray *)accountsForService:(NSString *)serviceName { + return [self accountsForService:serviceName error:nil]; +} + + ++ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error { + FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + query.service = serviceName; + return [query fetchAll:error]; +} + + +#if __IPHONE_4_0 && TARGET_OS_IPHONE ++ (CFTypeRef)accessibilityType { + return SSKeychainAccessibilityType; +} + + ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType { + CFRetain(accessibilityType); + if (SSKeychainAccessibilityType) { + CFRelease(SSKeychainAccessibilityType); + } + SSKeychainAccessibilityType = accessibilityType; +} +#endif + +@end diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h new file mode 100644 index 0000000000..2a96fc1c15 --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h @@ -0,0 +1,143 @@ +// +// SSKeychainQuery.h +// SSKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#if __has_feature(modules) + @import Foundation; + @import Security; +#else + #import + #import +#endif + +#if __IPHONE_7_0 || __MAC_10_9 + // Keychain synchronization available at compile time + #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 +#endif + +#if __IPHONE_3_0 || __MAC_10_9 + // Keychain access group available at compile time + #define SSKEYCHAIN_ACCESS_GROUP_AVAILABLE 1 +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { + SSKeychainQuerySynchronizationModeAny, + SSKeychainQuerySynchronizationModeNo, + SSKeychainQuerySynchronizationModeYes +}; +#endif + +/** + Simple interface for querying or modifying keychain items. + */ +@interface FLEXKeychainQuery : NSObject + +/** kSecAttrAccount */ +@property (nonatomic, copy) NSString *account; + +/** kSecAttrService */ +@property (nonatomic, copy) NSString *service; + +/** kSecAttrLabel */ +@property (nonatomic, copy) NSString *label; + +#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE +/** kSecAttrAccessGroup (only used on iOS) */ +@property (nonatomic, copy) NSString *accessGroup; +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** kSecAttrSynchronizable */ +@property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode; +#endif + +/** Root storage for password information */ +@property (nonatomic, copy) NSData *passwordData; + +/** + This property automatically transitions between an object and the value of + `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. + */ +@property (nonatomic, copy) id passwordObject; + +/** + Convenience accessor for setting and getting a password string. Passes through + to `passwordData` using UTF-8 string encoding. + */ +@property (nonatomic, copy) NSString *password; + + +///------------------------ +/// @name Saving & Deleting +///------------------------ + +/** + Save the receiver's attributes as a keychain item. Existing items with the + given account, service, and access group will first be deleted. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)save:(NSError **)error; + +/** + Delete keychain items that match the given account, service, and access group. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)deleteItem:(NSError **)error; + + +///--------------- +/// @name Fetching +///--------------- + +/** + Fetch all keychain items that match the given account, service, and access + group. The values of `password` and `passwordData` are ignored when fetching. + + @param error Populated should an error occur. + + @return An array of dictionaries that represent all matching keychain items or + `nil` should an error occur. + The order of the items is not determined. + */ +- (NSArray *> *)fetchAll:(NSError **)error; + +/** + Fetch the keychain item that matches the given account, service, and access + group. The `password` and `passwordData` properties will be populated unless + an error occurs. The values of `password` and `passwordData` are ignored when + fetching. + + @param error Populated should an error occur. + + @return `YES` if fetching was successful, `NO` otherwise. + */ +- (BOOL)fetch:(NSError **)error; + + +///----------------------------- +/// @name Synchronization Status +///----------------------------- + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** + Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define + SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization, + you should use this method. + + @return A value indicating if keychain synchronization is available + */ ++ (BOOL)isSynchronizationAvailable; +#endif + +@end diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m new file mode 100644 index 0000000000..ba78861bf2 --- /dev/null +++ b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m @@ -0,0 +1,316 @@ +// +// SSKeychainQuery.m +// SSKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#import "FLEXKeychainQuery.h" +#import "FLEXKeychain.h" + +@implementation FLEXKeychainQuery + +@synthesize account = _account; +@synthesize service = _service; +@synthesize label = _label; +@synthesize passwordData = _passwordData; + +#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE +@synthesize accessGroup = _accessGroup; +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +@synthesize synchronizationMode = _synchronizationMode; +#endif + +#pragma mark - Public + +- (BOOL)save:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account || !self.passwordData) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + NSMutableDictionary *query = nil; + NSMutableDictionary * searchQuery = [self query]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil); + if (status == errSecSuccess) {//item already exists, update it! + query = [[NSMutableDictionary alloc]init]; + [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + status = SecItemUpdate((__bridge CFDictionaryRef)(searchQuery), (__bridge CFDictionaryRef)(query)); + }else if(status == errSecItemNotFound){//item not found, create it! + query = [self query]; + if (self.label) { + [query setObject:self.label forKey:(__bridge id)kSecAttrLabel]; + } + [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + } + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + return (status == errSecSuccess);} + + +- (BOOL)deleteItem:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + NSMutableDictionary *query = [self query]; +#if TARGET_OS_IPHONE + status = SecItemDelete((__bridge CFDictionaryRef)query); +#else + // On Mac OS, SecItemDelete will not delete a key created in a different + // app, nor in a different version of the same app. + // + // To replicate the issue, save a password, change to the code and + // rebuild the app, and then attempt to delete that password. + // + // This was true in OS X 10.6 and probably later versions as well. + // + // Work around it by using SecItemCopyMatching and SecKeychainItemDelete. + CFTypeRef result = NULL; + [query setObject:@YES forKey:(__bridge id)kSecReturnRef]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status == errSecSuccess) { + status = SecKeychainItemDelete((SecKeychainItemRef)result); + CFRelease(result); + } +#endif + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (NSArray *)fetchAll:(NSError *__autoreleasing *)error { + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + return nil; + } + + return (__bridge_transfer NSArray *)result; +} + + +- (BOOL)fetch:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + CFTypeRef result = NULL; + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + + if (status != errSecSuccess) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + self.passwordData = (__bridge_transfer NSData *)result; + return YES; +} + + +#pragma mark - Accessors + +- (void)setPasswordObject:(id)object { + self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; +} + + +- (id)passwordObject { + if ([self.passwordData length]) { + return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; + } + return nil; +} + + +- (void)setPassword:(NSString *)password { + self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; +} + + +- (NSString *)password { + if ([self.passwordData length]) { + return [[NSString alloc] initWithData:self.passwordData encoding:NSUTF8StringEncoding]; + } + return nil; +} + + +#pragma mark - Synchronization Status + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE ++ (BOOL)isSynchronizationAvailable { +#if TARGET_OS_IPHONE + // Apple suggested way to check for 7.0 at runtime + // https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1; +#else + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; +#endif +} +#endif + + +#pragma mark - Private + +- (NSMutableDictionary *)query { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; + [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + + if (self.service) { + [dictionary setObject:self.service forKey:(__bridge id)kSecAttrService]; + } + + if (self.account) { + [dictionary setObject:self.account forKey:(__bridge id)kSecAttrAccount]; + } + +#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE +#if !TARGET_IPHONE_SIMULATOR + if (self.accessGroup) { + [dictionary setObject:self.accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE + if ([[self class] isSynchronizationAvailable]) { + id value; + + switch (self.synchronizationMode) { + case SSKeychainQuerySynchronizationModeNo: { + value = @NO; + break; + } + case SSKeychainQuerySynchronizationModeYes: { + value = @YES; + break; + } + case SSKeychainQuerySynchronizationModeAny: { + value = (__bridge id)(kSecAttrSynchronizableAny); + break; + } + } + + [dictionary setObject:value forKey:(__bridge id)(kSecAttrSynchronizable)]; + } +#endif + + return dictionary; +} + + ++ (NSError *)errorWithCode:(OSStatus) code { + static dispatch_once_t onceToken; + static NSBundle *resourcesBundle = nil; + dispatch_once(&onceToken, ^{ + NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:@"SSKeychain" withExtension:@"bundle"]; + resourcesBundle = [NSBundle bundleWithURL:url]; + }); + + NSString *message = nil; + switch (code) { + case errSecSuccess: return nil; + case SSKeychainErrorBadArguments: message = NSLocalizedStringFromTableInBundle(@"SSKeychainErrorBadArguments", @"SSKeychain", resourcesBundle, nil); break; + +#if TARGET_OS_IPHONE + case errSecUnimplemented: { + message = NSLocalizedStringFromTableInBundle(@"errSecUnimplemented", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecParam: { + message = NSLocalizedStringFromTableInBundle(@"errSecParam", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecAllocate: { + message = NSLocalizedStringFromTableInBundle(@"errSecAllocate", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecNotAvailable: { + message = NSLocalizedStringFromTableInBundle(@"errSecNotAvailable", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecDuplicateItem: { + message = NSLocalizedStringFromTableInBundle(@"errSecDuplicateItem", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecItemNotFound: { + message = NSLocalizedStringFromTableInBundle(@"errSecItemNotFound", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecInteractionNotAllowed: { + message = NSLocalizedStringFromTableInBundle(@"errSecInteractionNotAllowed", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecDecode: { + message = NSLocalizedStringFromTableInBundle(@"errSecDecode", @"SSKeychain", resourcesBundle, nil); + break; + } + case errSecAuthFailed: { + message = NSLocalizedStringFromTableInBundle(@"errSecAuthFailed", @"SSKeychain", resourcesBundle, nil); + break; + } + default: { + message = NSLocalizedStringFromTableInBundle(@"errSecDefault", @"SSKeychain", resourcesBundle, nil); + } +#else + default: + message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); +#endif + } + + NSDictionary *userInfo = nil; + if (message) { + userInfo = @{ NSLocalizedDescriptionKey : message }; + } + return [NSError errorWithDomain:kSSKeychainErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/FLEX.podspec b/FLEX.podspec index ed71a3d6cb..fb7a22842d 100644 --- a/FLEX.podspec +++ b/FLEX.podspec @@ -32,7 +32,7 @@ Pod::Spec.new do |spec| spec.platform = :ios, "9.0" spec.source = { :git => "https://github.com/Flipboard/FLEX.git", :tag => "#{spec.version}" } spec.source_files = "Classes/**/*.{h,m,mm}" - spec.frameworks = [ "Foundation", "UIKit", "CoreGraphics", "ImageIO", "QuartzCore", "WebKit" ] + spec.frameworks = [ "Foundation", "UIKit", "CoreGraphics", "ImageIO", "QuartzCore", "WebKit", "Security" ] spec.libraries = [ "z", "sqlite3" ] spec.requires_arc = true spec.public_header_files = [ "Classes/**/FLEXManager.h", "Classes/FLEX.h" ] diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 79e2e1df6b..25aadb023e 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -133,6 +133,12 @@ 3A4C95471B5B217D0088C3F2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4C95461B5B217D0088C3F2 /* libz.dylib */; }; 679F64861BD53B7B00A8C94C /* FLEXCookiesTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */; }; 679F64871BD53B7B00A8C94C /* FLEXCookiesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */; }; + 71E1C2132307FBB800F5032A /* FLEXKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */; }; + 71E1C2142307FBB800F5032A /* FLEXKeyChainTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */; }; + 71E1C2152307FBB800F5032A /* FLEXKeychainQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */; }; + 71E1C2172307FBB800F5032A /* FLEXKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */; }; + 71E1C2182307FBB800F5032A /* FLEXKeyChainTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */; }; + 71E1C2192307FBB800F5032A /* FLEXKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */; }; 7349FD6A22B93CDF00051810 /* FLEXColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7349FD6822B93CDF00051810 /* FLEXColor.h */; }; 7349FD6B22B93CDF00051810 /* FLEXColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 7349FD6922B93CDF00051810 /* FLEXColor.m */; }; 779B1ECE1C0C4D7C001F5E49 /* FLEXDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC01C0C4D7C001F5E49 /* FLEXDatabaseManager.h */; }; @@ -346,6 +352,12 @@ 3A4C95461B5B217D0088C3F2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; 679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXCookiesTableViewController.h; sourceTree = ""; }; 679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXCookiesTableViewController.m; sourceTree = ""; }; + 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeychain.h; sourceTree = ""; }; + 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyChainTableViewController.h; sourceTree = ""; }; + 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeychainQuery.h; sourceTree = ""; }; + 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeychain.m; sourceTree = ""; }; + 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyChainTableViewController.m; sourceTree = ""; }; + 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeychainQuery.m; sourceTree = ""; }; 7349FD6822B93CDF00051810 /* FLEXColor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXColor.h; sourceTree = ""; }; 7349FD6922B93CDF00051810 /* FLEXColor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXColor.m; sourceTree = ""; }; 779B1EC01C0C4D7C001F5E49 /* FLEXDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDatabaseManager.h; sourceTree = ""; }; @@ -616,6 +628,7 @@ 3A4C949A1B5B21410088C3F2 /* GlobalStateExplorers */ = { isa = PBXGroup; children = ( + 71E1C2092307FBB700F5032A /* KeyChain */, C3511B8E22D7C9740057BAB7 /* Globals */, 779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */, 3A4C94AD1B5B21410088C3F2 /* SystemLog */, @@ -700,6 +713,19 @@ name = Frameworks; sourceTree = ""; }; + 71E1C2092307FBB700F5032A /* KeyChain */ = { + isa = PBXGroup; + children = ( + 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */, + 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */, + 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */, + 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */, + 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */, + 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */, + ); + path = KeyChain; + sourceTree = ""; + }; 779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */ = { isa = PBXGroup; children = ( @@ -896,6 +922,7 @@ 3A4C95031B5B21410088C3F2 /* FLEXArgumentInputView.h in Headers */, 94A5151D1C4CA1F10063292F /* FLEXExplorerViewController.h in Headers */, C3F31D3F2267D883003C991A /* FLEXMultilineTableViewCell.h in Headers */, + 71E1C2132307FBB800F5032A /* FLEXKeychain.h in Headers */, 3A4C94C51B5B21410088C3F2 /* FLEXArrayExplorerViewController.h in Headers */, C3F31D432267D883003C991A /* FLEXTableView.h in Headers */, 3A4C94CB1B5B21410088C3F2 /* FLEXDictionaryExplorerViewController.h in Headers */, @@ -909,6 +936,7 @@ 779B1ED41C0C4D7C001F5E49 /* FLEXTableContentCell.h in Headers */, 3A4C952C1B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.h in Headers */, 3A4C94EF1B5B21410088C3F2 /* FLEXArgumentInputDateView.h in Headers */, + 71E1C2142307FBB800F5032A /* FLEXKeyChainTableViewController.h in Headers */, 3A4C94C71B5B21410088C3F2 /* FLEXClassExplorerViewController.h in Headers */, 3A4C94F71B5B21410088C3F2 /* FLEXArgumentInputNotSupportedView.h in Headers */, C3F31D3E2267D883003C991A /* FLEXTableViewCell.h in Headers */, @@ -939,6 +967,7 @@ 3A4C95401B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.h in Headers */, 3A4C95241B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h in Headers */, 94AAF0381BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h in Headers */, + 71E1C2152307FBB800F5032A /* FLEXKeychainQuery.h in Headers */, 94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */, C395D6D921789BD800BEAD4D /* FLEXColorExplorerViewController.h in Headers */, 94A515181C4CA1D70063292F /* FLEXManager+Private.h in Headers */, @@ -1087,6 +1116,7 @@ 3A4C94D01B5B21410088C3F2 /* FLEXImageExplorerViewController.m in Sources */, 679F64871BD53B7B00A8C94C /* FLEXCookiesTableViewController.m in Sources */, 3A4C94CE1B5B21410088C3F2 /* FLEXGlobalsEntry.m in Sources */, + 71E1C2192307FBB800F5032A /* FLEXKeychainQuery.m in Sources */, 3A4C94FE1B5B21410088C3F2 /* FLEXArgumentInputStructView.m in Sources */, C3F31D402267D883003C991A /* FLEXSubtitleTableViewCell.m in Sources */, 3A4C95431B5B21410088C3F2 /* FLEXNetworkObserver.m in Sources */, @@ -1115,6 +1145,7 @@ 3A4C94F81B5B21410088C3F2 /* FLEXArgumentInputNotSupportedView.m in Sources */, 3A4C95351B5B21410088C3F2 /* FLEXSystemLogTableViewController.m in Sources */, 3A4C95271B5B21410088C3F2 /* FLEXGlobalsTableViewController.m in Sources */, + 71E1C2172307FBB800F5032A /* FLEXKeychain.m in Sources */, C387C88422E0D24A00750E58 /* UIView+Layout.m in Sources */, 779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */, C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */, @@ -1145,6 +1176,7 @@ 3A4C95061B5B21410088C3F2 /* FLEXArgumentInputViewFactory.m in Sources */, 3A4C95291B5B21410088C3F2 /* FLEXInstancesTableViewController.m in Sources */, 3A4C952B1B5B21410088C3F2 /* FLEXLibrariesTableViewController.m in Sources */, + 71E1C2182307FBB800F5032A /* FLEXKeyChainTableViewController.m in Sources */, 94A5151E1C4CA1F10063292F /* FLEXExplorerViewController.m in Sources */, 3A4C95371B5B21410088C3F2 /* FLEXNetworkHistoryTableViewController.m in Sources */, C3511B9222D7C99E0057BAB7 /* FLEXTableViewSection.m in Sources */, From 8255c7fe79e78f8dabfba278853d4927773c8499 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Mon, 19 Aug 2019 13:42:57 -0500 Subject: [PATCH 29/45] General keychain cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - KeyChain → Keychain - Misc renames and refactorings - Change title - Tabs to spaces - Indentation --- .../Globals/FLEXGlobalsEntry.h | 2 +- .../Globals/FLEXGlobalsTableViewController.m | 8 +- .../KeyChain/FLEXKeychain.h | 198 ----------- .../KeyChain/FLEXKeychainQuery.h | 143 -------- .../KeyChain/FLEXKeychainQuery.m | 316 ------------------ .../Keychain/FLEXKeychain.h | 141 ++++++++ .../{KeyChain => Keychain}/FLEXKeychain.m | 96 +++--- .../Keychain/FLEXKeychainQuery.h | 112 +++++++ .../Keychain/FLEXKeychainQuery.m | 304 +++++++++++++++++ .../FLEXKeychainTableViewController.h} | 8 +- .../FLEXKeychainTableViewController.m} | 71 ++-- .../UICatalog/AAPLActionSheetViewController.m | 12 +- Example/UICatalog/AAPLAlertViewController.m | 18 +- FLEX.xcodeproj/project.pbxproj | 22 +- 14 files changed, 660 insertions(+), 791 deletions(-) delete mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h delete mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h delete mode 100644 Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m create mode 100644 Classes/GlobalStateExplorers/Keychain/FLEXKeychain.h rename Classes/GlobalStateExplorers/{KeyChain => Keychain}/FLEXKeychain.m (52%) create mode 100644 Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h create mode 100644 Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m rename Classes/GlobalStateExplorers/{KeyChain/FLEXKeyChainTableViewController.h => Keychain/FLEXKeychainTableViewController.h} (57%) rename Classes/GlobalStateExplorers/{KeyChain/FLEXKeyChainTableViewController.m => Keychain/FLEXKeychainTableViewController.m} (59%) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h index 727e73c6ea..10f4900eaf 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h @@ -19,7 +19,7 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) { FLEXGlobalsRowCookies, FLEXGlobalsRowSystemLibraries, FLEXGlobalsRowAppClasses, - FLEXGlobalsRowAppKeyChainItems, + FLEXGlobalsRowAppKeychainItems, FLEXGlobalsRowAppDelegate, FLEXGlobalsRowRootViewController, FLEXGlobalsRowUserDefaults, diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m index 2f586c6952..d1f5dc97c1 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m @@ -11,7 +11,7 @@ #import "FLEXRuntimeUtility.h" #import "FLEXLibrariesTableViewController.h" #import "FLEXClassesTableViewController.h" -#import "FLEXKeyChainTableViewController.h" +#import "FLEXKeychainTableViewController.h" #import "FLEXObjectExplorerViewController.h" #import "FLEXObjectExplorerFactory.h" #import "FLEXLiveObjectsTableViewController.h" @@ -57,8 +57,8 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row switch (row) { case FLEXGlobalsRowAppClasses: return [FLEXClassesTableViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowAppKeyChainItems: - return [FLEXKeyChainTableViewController flex_concreteGlobalsEntry:row]; + case FLEXGlobalsRowAppKeychainItems: + return [FLEXKeychainTableViewController flex_concreteGlobalsEntry:row]; case FLEXGlobalsRowAddressInspector: return [FLEXAddressExplorerCoordinator flex_concreteGlobalsEntry:row]; case FLEXGlobalsRowSystemLibraries: @@ -124,7 +124,7 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row @[ // FLEXGlobalsSectionAppShortcuts [self globalsEntryForRow:FLEXGlobalsRowMainBundle], [self globalsEntryForRow:FLEXGlobalsRowUserDefaults], - [self globalsEntryForRow:FLEXGlobalsRowAppKeyChainItems], + [self globalsEntryForRow:FLEXGlobalsRowAppKeychainItems], [self globalsEntryForRow:FLEXGlobalsRowApplication], [self globalsEntryForRow:FLEXGlobalsRowAppDelegate], [self globalsEntryForRow:FLEXGlobalsRowKeyWindow], diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h deleted file mode 100644 index 47e9adb45d..0000000000 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.h +++ /dev/null @@ -1,198 +0,0 @@ -// -// SSKeychain.h -// SSKeychain -// -// Created by Sam Soffes on 5/19/10. -// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. -// - -#if __has_feature(modules) - @import Foundation; -#else - #import -#endif - -/** - Error code specific to SSKeychain that can be returned in NSError objects. - For codes returned by the operating system, refer to SecBase.h for your - platform. - */ -typedef NS_ENUM(OSStatus, SSKeychainErrorCode) { - /** Some of the arguments were invalid. */ - SSKeychainErrorBadArguments = -1001, -}; - -/** SSKeychain error domain */ -extern NSString *const kSSKeychainErrorDomain; - -/** Account name. */ -extern NSString *const kSSKeychainAccountKey; - -/** - Time the item was created. - - The value will be a string. - */ -extern NSString *const kSSKeychainCreatedAtKey; - -/** Item class. */ -extern NSString *const kSSKeychainClassKey; - -/** Item description. */ -extern NSString *const kSSKeychainDescriptionKey; - -/** Item label. */ -extern NSString *const kSSKeychainLabelKey; - -/** Time the item was last modified. - - The value will be a string. - */ -extern NSString *const kSSKeychainLastModifiedKey; - -/** Where the item was created. */ -extern NSString *const kSSKeychainWhereKey; - -/** - Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system - Keychain on Mac OS X and iOS. - - This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. - SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it). - */ -@interface FLEXKeychain : NSObject - -#pragma mark - Classic methods - -/** - Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a - password for the given parameters. - - @param serviceName The service for which to return the corresponding password. - - @param account The account for which to return the corresponding password. - - @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't - have a password for the given parameters. - */ -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); - -/** - Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't have a - password for the given parameters. - - @param serviceName The service for which to return the corresponding password. - - @param account The account for which to return the corresponding password. - - @return Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't - have a password for the given parameters. - */ -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); - - -/** - Deletes a password from the Keychain. - - @param serviceName The service for which to delete the corresponding password. - - @param account The account for which to delete the corresponding password. - - @return Returns `YES` on success, or `NO` on failure. - */ -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); - - -/** - Sets a password in the Keychain. - - @param password The password to store in the Keychain. - - @param serviceName The service for which to set the corresponding password. - - @param account The account for which to set the corresponding password. - - @return Returns `YES` on success, or `NO` on failure. - */ -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); - -/** - Sets a password in the Keychain. - - @param password The password to store in the Keychain. - - @param serviceName The service for which to set the corresponding password. - - @param account The account for which to set the corresponding password. - - @return Returns `YES` on success, or `NO` on failure. - */ -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); - -/** - Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. - - See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the - dictionaries returned by this method. - - @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any - accounts. The order of the objects in the array isn't defined. - */ -+ (NSArray *> *)allAccounts; -+ (NSArray *> *)allAccounts:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); - - -/** - Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any - accounts for the given service. - - See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the - dictionaries returned by this method. - - @param serviceName The service for which to return the corresponding accounts. - - @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, or `nil` if the Keychain - doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. - */ -+ (NSArray *> *)accountsForService:(NSString *)serviceName; -+ (NSArray *> *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); - - -#pragma mark - Configuration - -#if __IPHONE_4_0 && TARGET_OS_IPHONE -/** - Returns the accessibility type for all future passwords saved to the Keychain. - - @return Returns the accessibility type. - - The return value will be `NULL` or one of the "Keychain Item Accessibility - Constants" used for determining when a keychain item should be readable. - - @see setAccessibilityType - */ -+ (CFTypeRef)accessibilityType; - -/** - Sets the accessibility type for all future passwords saved to the Keychain. - - @param accessibilityType One of the "Keychain Item Accessibility Constants" - used for determining when a keychain item should be readable. - - If the value is `NULL` (the default), the Keychain default will be used which - is highly insecure. You really should use at least `kSecAttrAccessibleAfterFirstUnlock` - for background applications or `kSecAttrAccessibleWhenUnlocked` for all - other applications. - - @see accessibilityType - */ -+ (void)setAccessibilityType:(CFTypeRef)accessibilityType; -#endif - -@end - diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h deleted file mode 100644 index 2a96fc1c15..0000000000 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.h +++ /dev/null @@ -1,143 +0,0 @@ -// -// SSKeychainQuery.h -// SSKeychain -// -// Created by Caleb Davenport on 3/19/13. -// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. -// - -#if __has_feature(modules) - @import Foundation; - @import Security; -#else - #import - #import -#endif - -#if __IPHONE_7_0 || __MAC_10_9 - // Keychain synchronization available at compile time - #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 -#endif - -#if __IPHONE_3_0 || __MAC_10_9 - // Keychain access group available at compile time - #define SSKEYCHAIN_ACCESS_GROUP_AVAILABLE 1 -#endif - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE -typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { - SSKeychainQuerySynchronizationModeAny, - SSKeychainQuerySynchronizationModeNo, - SSKeychainQuerySynchronizationModeYes -}; -#endif - -/** - Simple interface for querying or modifying keychain items. - */ -@interface FLEXKeychainQuery : NSObject - -/** kSecAttrAccount */ -@property (nonatomic, copy) NSString *account; - -/** kSecAttrService */ -@property (nonatomic, copy) NSString *service; - -/** kSecAttrLabel */ -@property (nonatomic, copy) NSString *label; - -#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE -/** kSecAttrAccessGroup (only used on iOS) */ -@property (nonatomic, copy) NSString *accessGroup; -#endif - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE -/** kSecAttrSynchronizable */ -@property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode; -#endif - -/** Root storage for password information */ -@property (nonatomic, copy) NSData *passwordData; - -/** - This property automatically transitions between an object and the value of - `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. - */ -@property (nonatomic, copy) id passwordObject; - -/** - Convenience accessor for setting and getting a password string. Passes through - to `passwordData` using UTF-8 string encoding. - */ -@property (nonatomic, copy) NSString *password; - - -///------------------------ -/// @name Saving & Deleting -///------------------------ - -/** - Save the receiver's attributes as a keychain item. Existing items with the - given account, service, and access group will first be deleted. - - @param error Populated should an error occur. - - @return `YES` if saving was successful, `NO` otherwise. - */ -- (BOOL)save:(NSError **)error; - -/** - Delete keychain items that match the given account, service, and access group. - - @param error Populated should an error occur. - - @return `YES` if saving was successful, `NO` otherwise. - */ -- (BOOL)deleteItem:(NSError **)error; - - -///--------------- -/// @name Fetching -///--------------- - -/** - Fetch all keychain items that match the given account, service, and access - group. The values of `password` and `passwordData` are ignored when fetching. - - @param error Populated should an error occur. - - @return An array of dictionaries that represent all matching keychain items or - `nil` should an error occur. - The order of the items is not determined. - */ -- (NSArray *> *)fetchAll:(NSError **)error; - -/** - Fetch the keychain item that matches the given account, service, and access - group. The `password` and `passwordData` properties will be populated unless - an error occurs. The values of `password` and `passwordData` are ignored when - fetching. - - @param error Populated should an error occur. - - @return `YES` if fetching was successful, `NO` otherwise. - */ -- (BOOL)fetch:(NSError **)error; - - -///----------------------------- -/// @name Synchronization Status -///----------------------------- - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE -/** - Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define - SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization, - you should use this method. - - @return A value indicating if keychain synchronization is available - */ -+ (BOOL)isSynchronizationAvailable; -#endif - -@end diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m b/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m deleted file mode 100644 index ba78861bf2..0000000000 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychainQuery.m +++ /dev/null @@ -1,316 +0,0 @@ -// -// SSKeychainQuery.m -// SSKeychain -// -// Created by Caleb Davenport on 3/19/13. -// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. -// - -#import "FLEXKeychainQuery.h" -#import "FLEXKeychain.h" - -@implementation FLEXKeychainQuery - -@synthesize account = _account; -@synthesize service = _service; -@synthesize label = _label; -@synthesize passwordData = _passwordData; - -#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE -@synthesize accessGroup = _accessGroup; -#endif - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE -@synthesize synchronizationMode = _synchronizationMode; -#endif - -#pragma mark - Public - -- (BOOL)save:(NSError *__autoreleasing *)error { - OSStatus status = SSKeychainErrorBadArguments; - if (!self.service || !self.account || !self.passwordData) { - if (error) { - *error = [[self class] errorWithCode:status]; - } - return NO; - } - NSMutableDictionary *query = nil; - NSMutableDictionary * searchQuery = [self query]; - status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil); - if (status == errSecSuccess) {//item already exists, update it! - query = [[NSMutableDictionary alloc]init]; - [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; - if (accessibilityType) { - [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; - } -#endif - status = SecItemUpdate((__bridge CFDictionaryRef)(searchQuery), (__bridge CFDictionaryRef)(query)); - }else if(status == errSecItemNotFound){//item not found, create it! - query = [self query]; - if (self.label) { - [query setObject:self.label forKey:(__bridge id)kSecAttrLabel]; - } - [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; - if (accessibilityType) { - [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; - } -#endif - status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); - } - if (status != errSecSuccess && error != NULL) { - *error = [[self class] errorWithCode:status]; - } - return (status == errSecSuccess);} - - -- (BOOL)deleteItem:(NSError *__autoreleasing *)error { - OSStatus status = SSKeychainErrorBadArguments; - if (!self.service || !self.account) { - if (error) { - *error = [[self class] errorWithCode:status]; - } - return NO; - } - - NSMutableDictionary *query = [self query]; -#if TARGET_OS_IPHONE - status = SecItemDelete((__bridge CFDictionaryRef)query); -#else - // On Mac OS, SecItemDelete will not delete a key created in a different - // app, nor in a different version of the same app. - // - // To replicate the issue, save a password, change to the code and - // rebuild the app, and then attempt to delete that password. - // - // This was true in OS X 10.6 and probably later versions as well. - // - // Work around it by using SecItemCopyMatching and SecKeychainItemDelete. - CFTypeRef result = NULL; - [query setObject:@YES forKey:(__bridge id)kSecReturnRef]; - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - if (status == errSecSuccess) { - status = SecKeychainItemDelete((SecKeychainItemRef)result); - CFRelease(result); - } -#endif - - if (status != errSecSuccess && error != NULL) { - *error = [[self class] errorWithCode:status]; - } - - return (status == errSecSuccess); -} - - -- (NSArray *)fetchAll:(NSError *__autoreleasing *)error { - NSMutableDictionary *query = [self query]; - [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; - [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; - if (accessibilityType) { - [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; - } -#endif - - CFTypeRef result = NULL; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - if (status != errSecSuccess && error != NULL) { - *error = [[self class] errorWithCode:status]; - return nil; - } - - return (__bridge_transfer NSArray *)result; -} - - -- (BOOL)fetch:(NSError *__autoreleasing *)error { - OSStatus status = SSKeychainErrorBadArguments; - if (!self.service || !self.account) { - if (error) { - *error = [[self class] errorWithCode:status]; - } - return NO; - } - - CFTypeRef result = NULL; - NSMutableDictionary *query = [self query]; - [query setObject:@YES forKey:(__bridge id)kSecReturnData]; - [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - - if (status != errSecSuccess) { - if (error) { - *error = [[self class] errorWithCode:status]; - } - return NO; - } - - self.passwordData = (__bridge_transfer NSData *)result; - return YES; -} - - -#pragma mark - Accessors - -- (void)setPasswordObject:(id)object { - self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; -} - - -- (id)passwordObject { - if ([self.passwordData length]) { - return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; - } - return nil; -} - - -- (void)setPassword:(NSString *)password { - self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; -} - - -- (NSString *)password { - if ([self.passwordData length]) { - return [[NSString alloc] initWithData:self.passwordData encoding:NSUTF8StringEncoding]; - } - return nil; -} - - -#pragma mark - Synchronization Status - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE -+ (BOOL)isSynchronizationAvailable { -#if TARGET_OS_IPHONE - // Apple suggested way to check for 7.0 at runtime - // https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html - return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1; -#else - return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; -#endif -} -#endif - - -#pragma mark - Private - -- (NSMutableDictionary *)query { - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; - [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; - - if (self.service) { - [dictionary setObject:self.service forKey:(__bridge id)kSecAttrService]; - } - - if (self.account) { - [dictionary setObject:self.account forKey:(__bridge id)kSecAttrAccount]; - } - -#ifdef SSKEYCHAIN_ACCESS_GROUP_AVAILABLE -#if !TARGET_IPHONE_SIMULATOR - if (self.accessGroup) { - [dictionary setObject:self.accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; - } -#endif -#endif - -#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE - if ([[self class] isSynchronizationAvailable]) { - id value; - - switch (self.synchronizationMode) { - case SSKeychainQuerySynchronizationModeNo: { - value = @NO; - break; - } - case SSKeychainQuerySynchronizationModeYes: { - value = @YES; - break; - } - case SSKeychainQuerySynchronizationModeAny: { - value = (__bridge id)(kSecAttrSynchronizableAny); - break; - } - } - - [dictionary setObject:value forKey:(__bridge id)(kSecAttrSynchronizable)]; - } -#endif - - return dictionary; -} - - -+ (NSError *)errorWithCode:(OSStatus) code { - static dispatch_once_t onceToken; - static NSBundle *resourcesBundle = nil; - dispatch_once(&onceToken, ^{ - NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:@"SSKeychain" withExtension:@"bundle"]; - resourcesBundle = [NSBundle bundleWithURL:url]; - }); - - NSString *message = nil; - switch (code) { - case errSecSuccess: return nil; - case SSKeychainErrorBadArguments: message = NSLocalizedStringFromTableInBundle(@"SSKeychainErrorBadArguments", @"SSKeychain", resourcesBundle, nil); break; - -#if TARGET_OS_IPHONE - case errSecUnimplemented: { - message = NSLocalizedStringFromTableInBundle(@"errSecUnimplemented", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecParam: { - message = NSLocalizedStringFromTableInBundle(@"errSecParam", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecAllocate: { - message = NSLocalizedStringFromTableInBundle(@"errSecAllocate", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecNotAvailable: { - message = NSLocalizedStringFromTableInBundle(@"errSecNotAvailable", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecDuplicateItem: { - message = NSLocalizedStringFromTableInBundle(@"errSecDuplicateItem", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecItemNotFound: { - message = NSLocalizedStringFromTableInBundle(@"errSecItemNotFound", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecInteractionNotAllowed: { - message = NSLocalizedStringFromTableInBundle(@"errSecInteractionNotAllowed", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecDecode: { - message = NSLocalizedStringFromTableInBundle(@"errSecDecode", @"SSKeychain", resourcesBundle, nil); - break; - } - case errSecAuthFailed: { - message = NSLocalizedStringFromTableInBundle(@"errSecAuthFailed", @"SSKeychain", resourcesBundle, nil); - break; - } - default: { - message = NSLocalizedStringFromTableInBundle(@"errSecDefault", @"SSKeychain", resourcesBundle, nil); - } -#else - default: - message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); -#endif - } - - NSDictionary *userInfo = nil; - if (message) { - userInfo = @{ NSLocalizedDescriptionKey : message }; - } - return [NSError errorWithDomain:kSSKeychainErrorDomain code:code userInfo:userInfo]; -} - -@end diff --git a/Classes/GlobalStateExplorers/Keychain/FLEXKeychain.h b/Classes/GlobalStateExplorers/Keychain/FLEXKeychain.h new file mode 100644 index 0000000000..f26c68d5b7 --- /dev/null +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychain.h @@ -0,0 +1,141 @@ +// +// FLEXKeychain.h +// +// Derived from: +// SSKeychain.h in SSKeychain +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#import + +/// Error code specific to FLEXKeychain that can be returned in NSError objects. +/// For codes returned by the operating system, refer to SecBase.h for your +/// platform. +typedef NS_ENUM(OSStatus, FLEXKeychainErrorCode) { + /// Some of the arguments were invalid. + FLEXKeychainErrorBadArguments = -1001, +}; + +/// FLEXKeychain error domain +extern NSString *const kFLEXKeychainErrorDomain; + +/// Account name. +extern NSString *const kFLEXKeychainAccountKey; + +/// Time the item was created. +/// +/// The value will be a string. +extern NSString *const kFLEXKeychainCreatedAtKey; + +/// Item class. +extern NSString *const kFLEXKeychainClassKey; + +/// Item description. +extern NSString *const kFLEXKeychainDescriptionKey; + +/// Item label. +extern NSString *const kFLEXKeychainLabelKey; + +/// Time the item was last modified. +/// +/// The value will be a string. +extern NSString *const kFLEXKeychainLastModifiedKey; + +/// Where the item was created. +extern NSString *const kFLEXKeychainWhereKey; + +/// A simple wrapper for accessing accounts, getting passwords, +/// setting passwords, and deleting passwords using the system Keychain. +@interface FLEXKeychain : NSObject + +#pragma mark - Classic methods + +/// @param serviceName The service for which to return the corresponding password. +/// @param account The account for which to return the corresponding password. +/// @return Returns a string containing the password for a given account and service, +/// or `nil` if the Keychain doesn't have a password for the given parameters. ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + +/// Returns a nsdata containing the password for a given account and service, +/// or `nil` if the Keychain doesn't have a password for the given parameters. +/// +/// @param serviceName The service for which to return the corresponding password. +/// @param account The account for which to return the corresponding password. +/// @return Returns a nsdata containing the password for a given account and service, +/// or `nil` if the Keychain doesn't have a password for the given parameters. ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + + +/// Deletes a password from the Keychain. +/// +/// @param serviceName The service for which to delete the corresponding password. +/// @param account The account for which to delete the corresponding password. +/// @return Returns `YES` on success, or `NO` on failure. ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + + +/// Sets a password in the Keychain. +/// +/// @param password The password to store in the Keychain. +/// @param serviceName The service for which to set the corresponding password. +/// @param account The account for which to set the corresponding password. +/// @return Returns `YES` on success, or `NO` on failure. ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + +/// Sets a password in the Keychain. +/// +/// @param password The password to store in the Keychain. +/// @param serviceName The service for which to set the corresponding password. +/// @param account The account for which to set the corresponding password. +/// @return Returns `YES` on success, or `NO` on failure. ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + +/// @return An array of dictionaries containing the Keychain's accounts, or `nil` if +/// the Keychain doesn't have any accounts. The order of the objects in the array isn't defined. +/// +/// @note See the `NSString` constants declared in FLEXKeychain.h for a list of keys that +/// can be used when accessing the dictionaries returned by this method. ++ (NSArray *> *)allAccounts; ++ (NSArray *> *)allAccounts:(NSError *__autoreleasing *)error; + +/// @param serviceName The service for which to return the corresponding accounts. +/// @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, +/// or `nil` if the Keychain doesn't have any accounts for the given `serviceName`. +/// The order of the objects in the array isn't defined. +/// +/// @note See the `NSString` constants declared in FLEXKeychain.h for a list of keys that +/// can be used when accessing the dictionaries returned by this method. ++ (NSArray *> *)accountsForService:(NSString *)serviceName; ++ (NSArray *> *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error; + + +#pragma mark - Configuration + +#if __IPHONE_4_0 && TARGET_OS_IPHONE +/// Returns the accessibility type for all future passwords saved to the Keychain. +/// +/// @return `NULL` or one of the "Keychain Item Accessibility +/// Constants" used for determining when a keychain item should be readable. ++ (CFTypeRef)accessibilityType; + +/// Sets the accessibility type for all future passwords saved to the Keychain. +/// +/// @param accessibilityType One of the "Keychain Item Accessibility Constants" +/// used for determining when a keychain item should be readable. +/// If the value is `NULL` (the default), the Keychain default will be used which +/// is highly insecure. You really should use at least `kSecAttrAccessibleAfterFirstUnlock` +/// for background applications or `kSecAttrAccessibleWhenUnlocked` for all +/// other applications. +/// +/// @note See Security/SecItem.h ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType; +#endif + +@end + diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m b/Classes/GlobalStateExplorers/Keychain/FLEXKeychain.m similarity index 52% rename from Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m rename to Classes/GlobalStateExplorers/Keychain/FLEXKeychain.m index f44042314a..37e179474a 100644 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeychain.m +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychain.m @@ -1,7 +1,8 @@ // -// SSKeychain.m -// SSKeychain +// FLEXKeychain.m // +// Forked from: +// SSKeychain.m in SSKeychain // Created by Sam Soffes on 5/19/10. // Copyright (c) 2010-2014 Sam Soffes. All rights reserved. // @@ -9,81 +10,75 @@ #import "FLEXKeychain.h" #import "FLEXKeychainQuery.h" -NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain"; -NSString *const kSSKeychainAccountKey = @"acct"; -NSString *const kSSKeychainCreatedAtKey = @"cdat"; -NSString *const kSSKeychainClassKey = @"labl"; -NSString *const kSSKeychainDescriptionKey = @"desc"; -NSString *const kSSKeychainLabelKey = @"labl"; -NSString *const kSSKeychainLastModifiedKey = @"mdat"; -NSString *const kSSKeychainWhereKey = @"svce"; +NSString * const kFLEXKeychainErrorDomain = @"com.flipboard.flex"; +NSString * const kFLEXKeychainAccountKey = @"acct"; +NSString * const kFLEXKeychainCreatedAtKey = @"cdat"; +NSString * const kFLEXKeychainClassKey = @"labl"; +NSString * const kFLEXKeychainDescriptionKey = @"desc"; +NSString * const kFLEXKeychainLabelKey = @"labl"; +NSString * const kFLEXKeychainLastModifiedKey = @"mdat"; +NSString * const kFLEXKeychainWhereKey = @"svce"; #if __IPHONE_4_0 && TARGET_OS_IPHONE - static CFTypeRef SSKeychainAccessibilityType = NULL; +static CFTypeRef FLEXKeychainAccessibilityType = NULL; #endif @implementation FLEXKeychain + (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { - return [self passwordForService:serviceName account:account error:nil]; + return [self passwordForService:serviceName account:account error:nil]; } - + (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; - query.service = serviceName; - query.account = account; - [query fetch:error]; - return query.password; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + return query.password; } + (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account { - return [self passwordDataForService:serviceName account:account error:nil]; + return [self passwordDataForService:serviceName account:account error:nil]; } + (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; query.service = serviceName; query.account = account; [query fetch:error]; - + return query.passwordData; } - + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account { - return [self deletePasswordForService:serviceName account:account error:nil]; + return [self deletePasswordForService:serviceName account:account error:nil]; } - + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; - query.service = serviceName; - query.account = account; - return [query deleteItem:error]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = serviceName; + query.account = account; + return [query deleteItem:error]; } - + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { - return [self setPassword:password forService:serviceName account:account error:nil]; + return [self setPassword:password forService:serviceName account:account error:nil]; } - + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; - query.service = serviceName; - query.account = account; - query.password = password; - return [query save:error]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = serviceName; + query.account = account; + query.password = password; + return [query save:error]; } + (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account { - return [self setPasswordData:password forService:serviceName account:account error:nil]; + return [self setPasswordData:password forService:serviceName account:account error:nil]; } - + (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; query.service = serviceName; query.account = account; query.passwordData = password; @@ -91,39 +86,34 @@ + (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName ac } + (NSArray *)allAccounts { - return [self allAccounts:nil]; + return [self allAccounts:nil]; } - + (NSArray *)allAccounts:(NSError *__autoreleasing *)error { return [self accountsForService:nil error:error]; } - + (NSArray *)accountsForService:(NSString *)serviceName { - return [self accountsForService:serviceName error:nil]; + return [self accountsForService:serviceName error:nil]; } - + (NSArray *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; query.service = serviceName; return [query fetchAll:error]; } - #if __IPHONE_4_0 && TARGET_OS_IPHONE + (CFTypeRef)accessibilityType { - return SSKeychainAccessibilityType; + return FLEXKeychainAccessibilityType; } - + (void)setAccessibilityType:(CFTypeRef)accessibilityType { - CFRetain(accessibilityType); - if (SSKeychainAccessibilityType) { - CFRelease(SSKeychainAccessibilityType); - } - SSKeychainAccessibilityType = accessibilityType; + CFRetain(accessibilityType); + if (FLEXKeychainAccessibilityType) { + CFRelease(FLEXKeychainAccessibilityType); + } + FLEXKeychainAccessibilityType = accessibilityType; } #endif diff --git a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h new file mode 100644 index 0000000000..e5500bfe7f --- /dev/null +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h @@ -0,0 +1,112 @@ +// +// FLEXKeychainQuery.h +// +// Derived from: +// SSKeychainQuery.h in SSKeychain +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#import +#import + +#if __IPHONE_7_0 || __MAC_10_9 +// Keychain synchronization available at compile time +#define FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 +#endif + +#if __IPHONE_3_0 || __MAC_10_9 +// Keychain access group available at compile time +#define FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE 1 +#endif + +#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE +typedef NS_ENUM(NSUInteger, FLEXKeychainQuerySynchronizationMode) { + FLEXKeychainQuerySynchronizationModeAny, + FLEXKeychainQuerySynchronizationModeNo, + FLEXKeychainQuerySynchronizationModeYes +}; +#endif + +/// Simple interface for querying or modifying keychain items. +@interface FLEXKeychainQuery : NSObject + +/// kSecAttrAccount +@property (nonatomic, copy) NSString *account; + +/// kSecAttrService +@property (nonatomic, copy) NSString *service; + +/// kSecAttrLabel +@property (nonatomic, copy) NSString *label; + +#ifdef FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE +/// kSecAttrAccessGroup (only used on iOS) +@property (nonatomic, copy) NSString *accessGroup; +#endif + +#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/// kSecAttrSynchronizable +@property (nonatomic) FLEXKeychainQuerySynchronizationMode synchronizationMode; +#endif + +/// Root storage for password information +@property (nonatomic, copy) NSData *passwordData; + +/// This property automatically transitions between an object and the value of +/// `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. +@property (nonatomic, copy) id passwordObject; + +/// Convenience accessor for setting and getting a password string. Passes through +/// to `passwordData` using UTF-8 string encoding. +@property (nonatomic, copy) NSString *password; + + +#pragma mark Saving & Deleting + +/// Save the receiver's attributes as a keychain item. Existing items with the +/// given account, service, and access group will first be deleted. +/// +/// @param error Populated should an error occur. +/// @return `YES` if saving was successful, `NO` otherwise. +- (BOOL)save:(NSError **)error; + +/// Delete keychain items that match the given account, service, and access group. +/// +/// @param error Populated should an error occur. +/// @return `YES` if saving was successful, `NO` otherwise. +- (BOOL)deleteItem:(NSError **)error; + + +#pragma mark Fetching + +/// Fetch all keychain items that match the given account, service, and access +/// group. The values of `password` and `passwordData` are ignored when fetching. +/// +/// @param error Populated should an error occur. +/// @return An array of dictionaries that represent all matching keychain items, +/// or `nil` should an error occur. The order of the items is not determined. +- (NSArray *> *)fetchAll:(NSError **)error; + +/// Fetch the keychain item that matches the given account, service, and access +/// group. The `password` and `passwordData` properties will be populated unless +/// an error occurs. The values of `password` and `passwordData` are ignored when +/// fetching. +/// +/// @param error Populated should an error occur. +/// @return `YES` if fetching was successful, `NO` otherwise. +- (BOOL)fetch:(NSError **)error; + + +#pragma mark Synchronization Status + +#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/// Returns a boolean indicating if keychain synchronization is available on the device at runtime. +/// The #define FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. +/// If you are checking for the presence of synchronization, you should use this method. +/// +/// @return A value indicating if keychain synchronization is available ++ (BOOL)isSynchronizationAvailable; +#endif + +@end diff --git a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m new file mode 100644 index 0000000000..6d88b45b4c --- /dev/null +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m @@ -0,0 +1,304 @@ +// +// FLEXKeychainQuery.m +// FLEXKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#import "FLEXKeychainQuery.h" +#import "FLEXKeychain.h" + +@implementation FLEXKeychainQuery + +#pragma mark - Public + +- (BOOL)save:(NSError *__autoreleasing *)error { + OSStatus status = FLEXKeychainErrorBadArguments; + if (!self.service || !self.account || !self.passwordData) { + if (error) { + *error = [self errorWithCode:status]; + } + return NO; + } + + NSMutableDictionary *query = nil; + NSMutableDictionary * searchQuery = [self query]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil); + if (status == errSecSuccess) {//item already exists, update it! + query = [[NSMutableDictionary alloc]init]; + query[(__bridge id)kSecValueData] = self.passwordData; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; + } +#endif + status = SecItemUpdate((__bridge CFDictionaryRef)(searchQuery), (__bridge CFDictionaryRef)(query)); + }else if (status == errSecItemNotFound){//item not found, create it! + query = [self query]; + if (self.label) { + query[(__bridge id)kSecAttrLabel] = self.label; + } + query[(__bridge id)kSecValueData] = self.passwordData; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; + } +#endif + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + } + + if (status != errSecSuccess && error != NULL) { + *error = [self errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (BOOL)deleteItem:(NSError *__autoreleasing *)error { + OSStatus status = FLEXKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [self errorWithCode:status]; + } + + return NO; + } + + NSMutableDictionary *query = [self query]; +#if TARGET_OS_IPHONE + status = SecItemDelete((__bridge CFDictionaryRef)query); +#else + // On Mac OS, SecItemDelete will not delete a key created in a different + // app, nor in a different version of the same app. + // + // To replicate the issue, save a password, change to the code and + // rebuild the app, and then attempt to delete that password. + // + // This was true in OS X 10.6 and probably later versions as well. + // + // Work around it by using SecItemCopyMatching and SecKeychainItemDelete. + CFTypeRef result = NULL; + query[(__bridge id)kSecReturnRef] = @YES; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status == errSecSuccess) { + status = SecKeychainItemDelete((SecKeychainItemRef)result); + CFRelease(result); + } +#endif + + if (status != errSecSuccess && error != NULL) { + *error = [self errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (NSArray *)fetchAll:(NSError *__autoreleasing *)error { + NSMutableDictionary *query = [self query]; + query[(__bridge id)kSecReturnAttributes] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [FLEXKeychain accessibilityType]; + if (accessibilityType) { + query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; + } +#endif + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status != errSecSuccess && error != NULL) { + *error = [self errorWithCode:status]; + return nil; + } + + return (__bridge_transfer NSArray *)result; +} + + +- (BOOL)fetch:(NSError *__autoreleasing *)error { + OSStatus status = FLEXKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [self errorWithCode:status]; + } + return NO; + } + + CFTypeRef result = NULL; + NSMutableDictionary *query = [self query]; + query[(__bridge id)kSecReturnData] = @YES; + query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + + if (status != errSecSuccess) { + if (error) { + *error = [self errorWithCode:status]; + } + return NO; + } + + self.passwordData = (__bridge_transfer NSData *)result; + return YES; +} + + +#pragma mark - Accessors + +- (void)setPasswordObject:(id)object { + self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; +} + + +- (id)passwordObject { + if (self.passwordData.length) { + return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; + } + + return nil; +} + + +- (void)setPassword:(NSString *)password { + self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; +} + + +- (NSString *)password { + if (self.passwordData.length) { + return [NSString stringWithCString:self.passwordData.bytes encoding:NSUTF8StringEncoding]; + } + + return nil; +} + + +#pragma mark - Synchronization Status + +#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE ++ (BOOL)isSynchronizationAvailable { +#if TARGET_OS_IPHONE + return @available(iOS 7.0, *); +#else + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; +#endif +} +#endif + + +#pragma mark - Private + +- (NSMutableDictionary *)query { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + dictionary[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + + if (self.service) { + dictionary[(__bridge id)kSecAttrService] = self.service; + } + + if (self.account) { + dictionary[(__bridge id)kSecAttrAccount] = self.account; + } + +#ifdef FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE +#if !TARGET_IPHONE_SIMULATOR + if (self.accessGroup) { + dictionary[(__bridge id)kSecAttrAccessGroup] = self.accessGroup; + } +#endif +#endif + +#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE + if ([[self class] isSynchronizationAvailable]) { + id value; + + switch (self.synchronizationMode) { + case FLEXKeychainQuerySynchronizationModeNo: { + value = @NO; + break; + } + case FLEXKeychainQuerySynchronizationModeYes: { + value = @YES; + break; + } + case FLEXKeychainQuerySynchronizationModeAny: { + value = (__bridge id)(kSecAttrSynchronizableAny); + break; + } + } + + dictionary[(__bridge id)(kSecAttrSynchronizable)] = value; + } +#endif + + return dictionary; +} + +- (NSError *)errorWithCode:(OSStatus)code { + static dispatch_once_t onceToken; + static NSBundle *resourcesBundle = nil; + dispatch_once(&onceToken, ^{ + NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:@"FLEXKeychain" withExtension:@"bundle"]; + resourcesBundle = [NSBundle bundleWithURL:url]; + }); + + NSString *message = nil; + switch (code) { + case errSecSuccess: return nil; + case FLEXKeychainErrorBadArguments: message = NSLocalizedStringFromTableInBundle(@"FLEXKeychainErrorBadArguments", @"FLEXKeychain", resourcesBundle, nil); break; + +#if TARGET_OS_IPHONE + case errSecUnimplemented: { + message = NSLocalizedStringFromTableInBundle(@"errSecUnimplemented", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecParam: { + message = NSLocalizedStringFromTableInBundle(@"errSecParam", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecAllocate: { + message = NSLocalizedStringFromTableInBundle(@"errSecAllocate", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecNotAvailable: { + message = NSLocalizedStringFromTableInBundle(@"errSecNotAvailable", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecDuplicateItem: { + message = NSLocalizedStringFromTableInBundle(@"errSecDuplicateItem", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecItemNotFound: { + message = NSLocalizedStringFromTableInBundle(@"errSecItemNotFound", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecInteractionNotAllowed: { + message = NSLocalizedStringFromTableInBundle(@"errSecInteractionNotAllowed", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecDecode: { + message = NSLocalizedStringFromTableInBundle(@"errSecDecode", @"FLEXKeychain", resourcesBundle, nil); + break; + } + case errSecAuthFailed: { + message = NSLocalizedStringFromTableInBundle(@"errSecAuthFailed", @"FLEXKeychain", resourcesBundle, nil); + break; + } + default: { + message = NSLocalizedStringFromTableInBundle(@"errSecDefault", @"FLEXKeychain", resourcesBundle, nil); + } +#else + default: + message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); +#endif + } + + NSDictionary *userInfo = message ? @{ NSLocalizedDescriptionKey : message } : nil; + return [NSError errorWithDomain:kFLEXKeychainErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.h similarity index 57% rename from Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h rename to Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.h index 88844a4822..c8705bb657 100644 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.h +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.h @@ -1,5 +1,5 @@ // -// FLEXKeyChainTableViewController.h +// FLEXKeychainTableViewController.h // FLEX // // Created by ray on 2019/8/17. @@ -9,10 +9,6 @@ #import "FLEXGlobalsEntry.h" #import "FLEXTableViewController.h" -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXKeyChainTableViewController : FLEXTableViewController +@interface FLEXKeychainTableViewController : FLEXTableViewController @end - -NS_ASSUME_NONNULL_END diff --git a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m similarity index 59% rename from Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m rename to Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m index 3889fa83fc..a7e0be0983 100644 --- a/Classes/GlobalStateExplorers/KeyChain/FLEXKeyChainTableViewController.m +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m @@ -1,5 +1,5 @@ // -// FLEXKeyChainTableViewController.m +// FLEXKeychainTableViewController.m // FLEX // // Created by ray on 2019/8/17. @@ -8,44 +8,41 @@ #import "FLEXKeychain.h" #import "FLEXKeychainQuery.h" -#import "FLEXKeyChainTableViewController.h" +#import "FLEXKeychainTableViewController.h" #import "FLEXUtility.h" -@interface FLEXKeyChainTableViewController () +@interface FLEXKeychainTableViewController () @property (nonatomic) NSArray *keyChainItems; @end -@implementation FLEXKeyChainTableViewController +@implementation FLEXKeychainTableViewController - (void)viewDidLoad { [super viewDidLoad]; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(clearKeyChain)]; - + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(clearKeychain)]; - _keyChainItems = [FLEXKeychain allAccounts]; - self.title = [NSString stringWithFormat:@"🔑 KeyChains (%lu)", (unsigned long)self.keyChainItems.count]; + self.keyChainItems = [FLEXKeychain allAccounts]; + self.title = [NSString stringWithFormat:@"🔑 Keychain Items (%lu)", (unsigned long)self.keyChainItems.count]; } -- (void)clearKeyChain +- (void)clearKeychain { - for (id account in _keyChainItems) { - - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; - - query.service = [account valueForKey:kSSKeychainWhereKey]; - query.account = [account valueForKey:kSSKeychainAccountKey]; + for (id account in self.keyChainItems) { + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = account[kFLEXKeychainWhereKey]; + query.account = account[kFLEXKeychainAccountKey]; - if(![query deleteItem:nil]) { + if (![query deleteItem:nil]) { NSLog(@"Delete Keychin Item Failed."); } } - _keyChainItems = [FLEXKeychain allAccounts]; + self.keyChainItems = [FLEXKeychain allAccounts]; [self.tableView reloadData]; } @@ -53,24 +50,17 @@ - (void)clearKeyChain + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return [NSString stringWithFormat:@"🔑 %@ KeyChain", [FLEXUtility applicationName]]; + return @"🔑 Keychain"; } + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - FLEXKeyChainTableViewController *keyChainViewController = [self new]; - - return keyChainViewController; + return [self new]; } #pragma mark - Table View Data Source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - return 1; -} - - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.keyChainItems.count; @@ -87,7 +77,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } NSDictionary *item = self.keyChainItems[indexPath.row]; - cell.textLabel.text = item[kSSKeychainAccountKey]; + cell.textLabel.text = item[kFLEXKeychainAccountKey]; return cell; } @@ -99,34 +89,27 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath { NSDictionary *item = self.keyChainItems[indexPath.row]; - FLEXKeychainQuery *query = [[FLEXKeychainQuery alloc] init]; - query.service = [item valueForKey:kSSKeychainWhereKey]; - query.account = [item valueForKey:kSSKeychainAccountKey]; + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = [item valueForKey:kFLEXKeychainWhereKey]; + query.account = [item valueForKey:kFLEXKeychainAccountKey]; [query fetch:nil]; NSString *msg = nil; - if ([query.password length]) - { + if (query.password.length) { msg = query.password; - } - - else if ([query.passwordData length]) - { - msg = [query.passwordData description]; - } - - else - { - msg = @"NO Data!"; + } else if (query.passwordData.length) { + msg = query.passwordData.description; + } else { + msg = @"No data"; } UIAlertController *cv = [UIAlertController alertControllerWithTitle:@"Password" message:msg preferredStyle:UIAlertControllerStyleAlert]; - [cv addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [cv addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { [cv dismissViewControllerAnimated:YES completion:nil]; }]]; - [cv addAction:[UIAlertAction actionWithTitle:@"Copy" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [cv addAction:[UIAlertAction actionWithTitle:@"Copy" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = msg; }]]; diff --git a/Example/UICatalog/AAPLActionSheetViewController.m b/Example/UICatalog/AAPLActionSheetViewController.m index fde7ec696e..045e8a48fa 100644 --- a/Example/UICatalog/AAPLActionSheetViewController.m +++ b/Example/UICatalog/AAPLActionSheetViewController.m @@ -67,11 +67,11 @@ - (void)showOkayCancelActionSheet { NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil); NSString *destructiveButtonTitle = NSLocalizedString(@"OK", nil); - UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:cancelButtonTitle destructiveButtonTitle:destructiveButtonTitle otherButtonTitles:nil]; + UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:cancelButtonTitle destructiveButtonTitle:destructiveButtonTitle otherButtonTitles:nil]; - actionSheet.actionSheetStyle = UIActionSheetStyleDefault; + actionSheet.actionSheetStyle = UIActionSheetStyleDefault; - [actionSheet showInView:self.view]; + [actionSheet showInView:self.view]; } // Show a dialog with two custom buttons. @@ -79,11 +79,11 @@ - (void)showOtherActionSheet { NSString *destructiveButtonTitle = NSLocalizedString(@"Destructive Choice", nil); NSString *otherButtonTitle = NSLocalizedString(@"Safe Choice", nil); - UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:destructiveButtonTitle otherButtonTitles:otherButtonTitle, nil]; + UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:destructiveButtonTitle otherButtonTitles:otherButtonTitle, nil]; - actionSheet.actionSheetStyle = UIActionSheetStyleDefault; + actionSheet.actionSheetStyle = UIActionSheetStyleDefault; - [actionSheet showInView:self.view]; + [actionSheet showInView:self.view]; } diff --git a/Example/UICatalog/AAPLAlertViewController.m b/Example/UICatalog/AAPLAlertViewController.m index 583f011186..07afea7fce 100644 --- a/Example/UICatalog/AAPLAlertViewController.m +++ b/Example/UICatalog/AAPLAlertViewController.m @@ -71,9 +71,9 @@ - (void)showSimpleAlert { NSString *message = NSLocalizedString(@"A message should be a short, complete sentence.", nil); NSString *cancelButtonTitle = NSLocalizedString(@"OK", nil); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil]; - [alert show]; + [alert show]; } // Show an alert with an "Okay" and "Cancel" button. @@ -83,9 +83,9 @@ - (void)showOkayCancelAlert { NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil); NSString *otherButtonTitle = NSLocalizedString(@"OK", nil); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; - [alert show]; + [alert show]; } // Show an alert with two custom buttons. @@ -96,9 +96,9 @@ - (void)showOtherAlert { NSString *otherButtonTitleOne = NSLocalizedString(@"Choice One", nil); NSString *otherButtonTitleTwo = NSLocalizedString(@"Choice Two", nil); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitleOne, otherButtonTitleTwo, nil]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitleOne, otherButtonTitleTwo, nil]; - [alert show]; + [alert show]; } // Show a text entry alert with two custom buttons. @@ -108,7 +108,7 @@ - (void)showTextEntryAlert { NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil); NSString *otherButtonTitle = NSLocalizedString(@"OK", nil); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; @@ -122,9 +122,9 @@ - (void)showSecureTextEntryAlert { NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil); NSString *otherButtonTitle = NSLocalizedString(@"OK", nil); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitle, nil]; - alert.alertViewStyle = UIAlertViewStyleSecureTextInput; + alert.alertViewStyle = UIAlertViewStyleSecureTextInput; [alert show]; } diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 25aadb023e..5105572a80 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -134,10 +134,10 @@ 679F64861BD53B7B00A8C94C /* FLEXCookiesTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */; }; 679F64871BD53B7B00A8C94C /* FLEXCookiesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */; }; 71E1C2132307FBB800F5032A /* FLEXKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */; }; - 71E1C2142307FBB800F5032A /* FLEXKeyChainTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */; }; + 71E1C2142307FBB800F5032A /* FLEXKeychainTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20C2307FBB700F5032A /* FLEXKeychainTableViewController.h */; }; 71E1C2152307FBB800F5032A /* FLEXKeychainQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */; }; 71E1C2172307FBB800F5032A /* FLEXKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */; }; - 71E1C2182307FBB800F5032A /* FLEXKeyChainTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */; }; + 71E1C2182307FBB800F5032A /* FLEXKeychainTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C2102307FBB700F5032A /* FLEXKeychainTableViewController.m */; }; 71E1C2192307FBB800F5032A /* FLEXKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */; }; 7349FD6A22B93CDF00051810 /* FLEXColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7349FD6822B93CDF00051810 /* FLEXColor.h */; }; 7349FD6B22B93CDF00051810 /* FLEXColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 7349FD6922B93CDF00051810 /* FLEXColor.m */; }; @@ -353,10 +353,10 @@ 679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXCookiesTableViewController.h; sourceTree = ""; }; 679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXCookiesTableViewController.m; sourceTree = ""; }; 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeychain.h; sourceTree = ""; }; - 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyChainTableViewController.h; sourceTree = ""; }; + 71E1C20C2307FBB700F5032A /* FLEXKeychainTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeychainTableViewController.h; sourceTree = ""; }; 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeychainQuery.h; sourceTree = ""; }; 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeychain.m; sourceTree = ""; }; - 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyChainTableViewController.m; sourceTree = ""; }; + 71E1C2102307FBB700F5032A /* FLEXKeychainTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeychainTableViewController.m; sourceTree = ""; }; 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeychainQuery.m; sourceTree = ""; }; 7349FD6822B93CDF00051810 /* FLEXColor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXColor.h; sourceTree = ""; }; 7349FD6922B93CDF00051810 /* FLEXColor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXColor.m; sourceTree = ""; }; @@ -628,7 +628,7 @@ 3A4C949A1B5B21410088C3F2 /* GlobalStateExplorers */ = { isa = PBXGroup; children = ( - 71E1C2092307FBB700F5032A /* KeyChain */, + 71E1C2092307FBB700F5032A /* Keychain */, C3511B8E22D7C9740057BAB7 /* Globals */, 779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */, 3A4C94AD1B5B21410088C3F2 /* SystemLog */, @@ -713,17 +713,17 @@ name = Frameworks; sourceTree = ""; }; - 71E1C2092307FBB700F5032A /* KeyChain */ = { + 71E1C2092307FBB700F5032A /* Keychain */ = { isa = PBXGroup; children = ( 71E1C20B2307FBB700F5032A /* FLEXKeychain.h */, 71E1C20F2307FBB700F5032A /* FLEXKeychain.m */, 71E1C20D2307FBB700F5032A /* FLEXKeychainQuery.h */, 71E1C2112307FBB700F5032A /* FLEXKeychainQuery.m */, - 71E1C20C2307FBB700F5032A /* FLEXKeyChainTableViewController.h */, - 71E1C2102307FBB700F5032A /* FLEXKeyChainTableViewController.m */, + 71E1C20C2307FBB700F5032A /* FLEXKeychainTableViewController.h */, + 71E1C2102307FBB700F5032A /* FLEXKeychainTableViewController.m */, ); - path = KeyChain; + path = Keychain; sourceTree = ""; }; 779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */ = { @@ -936,7 +936,7 @@ 779B1ED41C0C4D7C001F5E49 /* FLEXTableContentCell.h in Headers */, 3A4C952C1B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.h in Headers */, 3A4C94EF1B5B21410088C3F2 /* FLEXArgumentInputDateView.h in Headers */, - 71E1C2142307FBB800F5032A /* FLEXKeyChainTableViewController.h in Headers */, + 71E1C2142307FBB800F5032A /* FLEXKeychainTableViewController.h in Headers */, 3A4C94C71B5B21410088C3F2 /* FLEXClassExplorerViewController.h in Headers */, 3A4C94F71B5B21410088C3F2 /* FLEXArgumentInputNotSupportedView.h in Headers */, C3F31D3E2267D883003C991A /* FLEXTableViewCell.h in Headers */, @@ -1176,7 +1176,7 @@ 3A4C95061B5B21410088C3F2 /* FLEXArgumentInputViewFactory.m in Sources */, 3A4C95291B5B21410088C3F2 /* FLEXInstancesTableViewController.m in Sources */, 3A4C952B1B5B21410088C3F2 /* FLEXLibrariesTableViewController.m in Sources */, - 71E1C2182307FBB800F5032A /* FLEXKeyChainTableViewController.m in Sources */, + 71E1C2182307FBB800F5032A /* FLEXKeychainTableViewController.m in Sources */, 94A5151E1C4CA1F10063292F /* FLEXExplorerViewController.m in Sources */, 3A4C95371B5B21410088C3F2 /* FLEXNetworkHistoryTableViewController.m in Sources */, C3511B9222D7C99E0057BAB7 /* FLEXTableViewSection.m in Sources */, From 4be2b119d14bd4749adc0788f4c3edddd23e1325 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Tue, 20 Aug 2019 19:38:28 -0500 Subject: [PATCH 30/45] Add more powerful alerts to the keychain screen --- .../FLEXKeychainTableViewController.m | 125 ++++++++++++------ 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m index a7e0be0983..a6d49c183f 100644 --- a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainTableViewController.m @@ -23,29 +23,78 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(clearKeychain)]; - + self.navigationItem.rightBarButtonItems = @[ + [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(trashPressed) + ], + [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPressed) + ], + ]; + + [self refreshKeychainItems]; +} + +- (void)refreshKeychainItems +{ self.keyChainItems = [FLEXKeychain allAccounts]; self.title = [NSString stringWithFormat:@"🔑 Keychain Items (%lu)", (unsigned long)self.keyChainItems.count]; } -- (void)clearKeychain +#pragma mark Buttons + +- (void)trashPressed { - - for (id account in self.keyChainItems) { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = account[kFLEXKeychainWhereKey]; - query.account = account[kFLEXKeychainAccountKey]; - - if (![query deleteItem:nil]) { - NSLog(@"Delete Keychin Item Failed."); - } - } - - self.keyChainItems = [FLEXKeychain allAccounts]; - [self.tableView reloadData]; + [FLEXAlert makeSheet:^(FLEXAlert *make) { + make.title(@"Clear Keychain"); + make.message(@"This will remove all keychain items for this app.\n"); + make.message(@"This action cannot be undone. Are you sure?"); + make.button(@"Yes, clear the keychain").destructiveStyle().handler(^(NSArray *strings) { + for (id account in self.keyChainItems) { + FLEXKeychainQuery *query = [FLEXKeychainQuery new]; + query.service = account[kFLEXKeychainWhereKey]; + query.account = account[kFLEXKeychainAccountKey]; + + // Delete item or display error + NSError *error = nil; + if (![query deleteItem:&error]) { + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Error Deleting Item"); + make.message(error.localizedDescription); + } showFrom:self]; + } + } + + [self refreshKeychainItems]; + [self.tableView reloadData]; + }); + make.button(@"Cancel").cancelStyle(); + } showFrom:self]; } +- (void)addPressed +{ + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Add Keychain Item"); + make.textField(@"Service name, i.e. Instagram"); + make.textField(@"Account, i.e. username@example.com"); + make.textField(@"Password"); + make.button(@"Cancel").cancelStyle(); + make.button(@"Save").handler(^(NSArray *strings) { + // Display errors + NSError *error = nil; + if (![FLEXKeychain setPassword:strings[2] forService:strings[0] account:strings[1] error:&error]) { + [FLEXAlert showAlert:@"Error" message:error.localizedDescription from:self]; + } + + [self refreshKeychainItems]; + [self.tableView reloadData]; + }); + } showFrom:self]; +} + + + #pragma mark - FLEXGlobalsEntry + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row @@ -90,31 +139,27 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath NSDictionary *item = self.keyChainItems[indexPath.row]; FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = [item valueForKey:kFLEXKeychainWhereKey]; - query.account = [item valueForKey:kFLEXKeychainAccountKey]; + query.service = item[kFLEXKeychainWhereKey]; + query.account = item[kFLEXKeychainAccountKey]; [query fetch:nil]; - - NSString *msg = nil; - - if (query.password.length) { - msg = query.password; - } else if (query.passwordData.length) { - msg = query.passwordData.description; - } else { - msg = @"No data"; - } - - UIAlertController *cv = [UIAlertController alertControllerWithTitle:@"Password" message:msg preferredStyle:UIAlertControllerStyleAlert]; - [cv addAction:[UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { - [cv dismissViewControllerAnimated:YES completion:nil]; - }]]; - - [cv addAction:[UIAlertAction actionWithTitle:@"Copy" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - pasteboard.string = msg; - }]]; - - [self presentViewController:cv animated:YES completion:nil]; + + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(query.service); + make.message(@"Service: ").message(query.service); + make.message(@"\nAccount: ").message(query.account); + make.message(@"\nPassword: ").message(query.password); + + make.button(@"Copy Service").handler(^(NSArray *strings) { + UIPasteboard.generalPasteboard.string = query.service; + }); + make.button(@"Copy Account").handler(^(NSArray *strings) { + UIPasteboard.generalPasteboard.string = query.account; + }); + make.button(@"Copy Password").handler(^(NSArray *strings) { + UIPasteboard.generalPasteboard.string = query.password; + }); + make.button(@"Dismiss").cancelStyle(); + } showFrom:self]; } @end From 555b57941dfc1f86fb87f820d7618db8ebf9d8ed Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Tue, 20 Aug 2019 19:44:17 -0500 Subject: [PATCH 31/45] Add SSKeychain license --- .../Keychain/SSKeychain_LICENSE | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Classes/GlobalStateExplorers/Keychain/SSKeychain_LICENSE diff --git a/Classes/GlobalStateExplorers/Keychain/SSKeychain_LICENSE b/Classes/GlobalStateExplorers/Keychain/SSKeychain_LICENSE new file mode 100644 index 0000000000..b63e07723d --- /dev/null +++ b/Classes/GlobalStateExplorers/Keychain/SSKeychain_LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010-2012 Sam Soffes. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 07f0b07a91d89428dbe9c29840c9ac7ea9f6726a Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Wed, 21 Aug 2019 13:28:26 -0500 Subject: [PATCH 32/45] Fix #324, crash when viewing NSNumber --- .../FLEXInstancesTableViewController.m | 3 ++- Classes/Utility/FLEXRuntimeUtility.m | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m index f88a38fe58..ee406b9add 100644 --- a/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m +++ b/Classes/GlobalStateExplorers/FLEXInstancesTableViewController.m @@ -61,7 +61,8 @@ + (instancetype)instancesTableViewControllerForClassName:(NSString *)className NSMutableArray *instances = [NSMutableArray array]; [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) { if (strcmp(classNameCString, class_getName(actualClass)) == 0) { - // Note: objects of certain classes crash when retain is called. It is up to the user to avoid tapping into instance lists for these classes. + // Note: objects of certain classes crash when retain is called. + // It is up to the user to avoid tapping into instance lists for these classes. // Ex. OS_dispatch_queue_specific_queue // In the future, we could provide some kind of warning for classes that are known to be problematic. if (malloc_size((__bridge const void *)(object)) > 0) { diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index f93c5eaa15..136318d537 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -398,8 +398,21 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * return nil; } - // Build the invocation + // Probably an unsupported type encoding, like bitfields + // or inline arrays. In the future, we could calculate + // the return length on our own. For now, we abort. + // + // For future reference, the code here will get the true type encoding. + // NSMethodSignature will convert {?=b8b4b1b1b18[8S]} to {?} + // A solution might involve hooking NSGetSizeAndAlignment. + // + // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector)); NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector]; + if (!methodSignature.methodReturnLength) { + return nil; + } + + // Build the invocation NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setSelector:selector]; [invocation setTarget:object]; @@ -454,9 +467,6 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * // Try to invoke the invocation but guard against an exception being thrown. id returnObject = nil; @try { - // Some methods are not fit to be called... - // Looking at you -[UIResponder(UITextInputAdditions) _caretRect] - [invocation invoke]; // Retrieve the return value and box if necessary. const char *returnType = methodSignature.methodReturnType; @@ -467,6 +477,7 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * [invocation getReturnValue:&objectReturnedFromMethod]; returnObject = objectReturnedFromMethod; } else if (returnType[0] != FLEXTypeEncodingVoid) { + NSAssert(methodSignature.methodReturnLength, @"Memory corruption lies ahead"); // Will use arbitrary buffer for return value and box it. void *returnValue = malloc(methodSignature.methodReturnLength); From d537d3c79e8ff7f4b2243e2133a351748e4e661b Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Sat, 14 Sep 2019 15:10:31 -0500 Subject: [PATCH 33/45] Fix image viewer not always showing share sheet --- Classes/Core/FLEXTableViewController.m | 8 +++++++ .../FLEXImagePreviewViewController.m | 23 ++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Classes/Core/FLEXTableViewController.m b/Classes/Core/FLEXTableViewController.m index 5e34087ce6..9a50b0f093 100644 --- a/Classes/Core/FLEXTableViewController.m +++ b/Classes/Core/FLEXTableViewController.m @@ -163,6 +163,14 @@ - (void)viewDidAppear:(BOOL)animated { } } +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + + if (self.searchController.active) { + self.searchController.active = NO; + } +} + #pragma mark - Private - (void)debounce:(void(^)())block { diff --git a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m index 4c88d37965..c1c6d744f5 100644 --- a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m +++ b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m @@ -81,29 +81,36 @@ - (void)centerContentInScrollViewIfNeeded - (void)actionButtonPressed:(id)sender { - static BOOL CanSaveToCameraRoll = NO; + static BOOL canSaveToCameraRoll = NO, didShowWarning = NO; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if ([UIDevice currentDevice].systemVersion.floatValue < 10) { - CanSaveToCameraRoll = YES; + canSaveToCameraRoll = YES; return; } NSBundle *mainBundle = [NSBundle mainBundle]; if ([mainBundle.infoDictionary.allKeys containsObject:@"NSPhotoLibraryUsageDescription"]) { - CanSaveToCameraRoll = YES; - } else { - NSLog(@"Add NSPhotoLibraryUsageDescription in app's Info.plist for saving captured image into camera roll."); + canSaveToCameraRoll = YES; } }); UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[self.image] applicationActivities:@[]]; - if (!CanSaveToCameraRoll) { + if (!canSaveToCameraRoll && !didShowWarning) { activityVC.excludedActivityTypes = @[UIActivityTypeSaveToCameraRoll]; + + didShowWarning = YES; + NSString *msg = @"Add 'NSPhotoLibraryUsageDescription' to this app's Info.plist to save images."; + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Reminder").message(msg); + make.button(@"OK").handler(^(NSArray *strings) { + [self presentViewController:activityVC animated:YES completion:nil]; + }); + } showFrom:self]; + } else { + [self presentViewController:activityVC animated:YES completion:nil]; } - - [self presentViewController:activityVC animated:YES completion:nil]; } @end From 8a762a66ae1a2d666d1ca1f499c753ecbb01f196 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Wed, 21 Aug 2019 15:34:57 -0500 Subject: [PATCH 34/45] Utilize NSURLQueryItem for storing query params --- ...workTransactionDetailTableViewController.m | 28 ++++++++++++++++--- Classes/Utility/FLEXUtility.h | 2 +- Classes/Utility/FLEXUtility.m | 28 ++++++------------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m index c782132f6a..c8503f6aff 100644 --- a/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m +++ b/Classes/Network/FLEXNetworkTransactionDetailTableViewController.m @@ -403,7 +403,7 @@ + (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransact NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; if ([contentType hasPrefix:@"application/x-www-form-urlencoded"]) { NSString *bodyString = [NSString stringWithCString:[self postBodyDataForTransaction:transaction].bytes encoding:NSUTF8StringEncoding]; - postBodySection.rows = [self networkDetailRowsFromDictionary:[FLEXUtility dictionaryFromQuery:bodyString]]; + postBodySection.rows = [self networkDetailRowsFromQueryItems:[FLEXUtility itemsFromQueryString:bodyString]]; } } return postBodySection; @@ -411,10 +411,10 @@ + (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXNetworkTransact + (FLEXNetworkDetailSection *)queryParametersSectionForTransaction:(FLEXNetworkTransaction *)transaction { - NSDictionary *queryDictionary = [FLEXUtility dictionaryFromQuery:transaction.request.URL.query]; + NSArray *queries = [FLEXUtility itemsFromQueryString:transaction.request.URL.query]; FLEXNetworkDetailSection *querySection = [FLEXNetworkDetailSection new]; querySection.title = @"Query Parameters"; - querySection.rows = [self networkDetailRowsFromDictionary:queryDictionary]; + querySection.rows = [self networkDetailRowsFromQueryItems:queries]; return querySection; } @@ -432,8 +432,9 @@ + (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkT + (NSArray *)networkDetailRowsFromDictionary:(NSDictionary *)dictionary { - NSMutableArray *rows = [NSMutableArray arrayWithCapacity:dictionary.count]; + NSMutableArray *rows = [NSMutableArray new]; NSArray *sortedKeys = [dictionary.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + for (NSString *key in sortedKeys) { id value = dictionary[key]; FLEXNetworkDetailRow *row = [FLEXNetworkDetailRow new]; @@ -441,6 +442,25 @@ + (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXNetworkT row.detailText = [value description]; [rows addObject:row]; } + + return rows.copy; +} + ++ (NSArray *)networkDetailRowsFromQueryItems:(NSArray *)items +{ + // Sort the items by name + items = [items sortedArrayUsingComparator:^NSComparisonResult(NSURLQueryItem *item1, NSURLQueryItem *item2) { + return [item1.name caseInsensitiveCompare:item2.name]; + }]; + + NSMutableArray *rows = [NSMutableArray new]; + for (NSURLQueryItem *item in items) { + FLEXNetworkDetailRow *row = [FLEXNetworkDetailRow new]; + row.title = item.name; + row.detailText = item.value; + [rows addObject:row]; + } + return [rows copy]; } diff --git a/Classes/Utility/FLEXUtility.h b/Classes/Utility/FLEXUtility.h index 1f2cdb0b9e..b4764db9fc 100644 --- a/Classes/Utility/FLEXUtility.h +++ b/Classes/Utility/FLEXUtility.h @@ -44,7 +44,7 @@ + (NSString *)stringFromRequestDuration:(NSTimeInterval)duration; + (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response; + (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response; -+ (NSDictionary *)dictionaryFromQuery:(NSString *)query; ++ (NSArray *)itemsFromQueryString:(NSString *)query; + (NSString *)prettyJSONStringFromData:(NSData *)data; + (BOOL)isValidJSONData:(NSData *)data; + (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData; diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index 93bc1a525c..d718ce9215 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -276,19 +276,17 @@ + (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response + (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response { - NSIndexSet *errorStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(400, 200)]; - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - return [errorStatusCodes containsIndex:httpResponse.statusCode]; + return httpResponse.statusCode >= 400; } return NO; } -+ (NSDictionary *)dictionaryFromQuery:(NSString *)query ++ (NSArray *)itemsFromQueryString:(NSString *)query { - NSMutableDictionary *queryDictionary = [NSMutableDictionary dictionary]; + NSMutableArray *items = [NSMutableArray new]; // [a=1, b=2, c=3] NSArray *queryComponents = [query componentsSeparatedByString:@"&"]; @@ -296,24 +294,14 @@ + (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response // [a, 1] NSArray *components = [keyValueString componentsSeparatedByString:@"="]; if (components.count == 2) { - NSString *key = [components.firstObject stringByRemovingPercentEncoding]; - id value = [components.lastObject stringByRemovingPercentEncoding]; - - // Handle multiple entries under the same key as an array - id existingEntry = queryDictionary[key]; - if (existingEntry) { - if ([existingEntry isKindOfClass:[NSArray class]]) { - value = [existingEntry arrayByAddingObject:value]; - } else { - value = @[existingEntry, value]; - } - } - - [queryDictionary setObject:value forKey:key]; + NSString *key = components.firstObject.stringByRemovingPercentEncoding; + NSString *value = components.lastObject.stringByRemovingPercentEncoding; + + [items addObject:[NSURLQueryItem queryItemWithName:key value:value]]; } } - return queryDictionary; + return items.copy; } + (NSString *)prettyJSONStringFromData:(NSData *)data From f582c9ae0d7fa7d602ce3020deb312a88124082b Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Sat, 14 Sep 2019 15:22:31 -0500 Subject: [PATCH 35/45] Misc cleanup --- .../FLEXExplorerViewController.m | 2 +- .../FLEXTableContentViewController.m | 2 +- .../FLEXDefaultsExplorerViewController.m | 2 +- .../FLEXObjectExplorerViewController.m | 30 ------------------- .../FLEXObjectExplorerFactory.m | 2 +- Classes/Utility/FLEXUtility.m | 6 ++-- .../FLEXImagePreviewViewController.m | 2 +- 7 files changed, 8 insertions(+), 38 deletions(-) diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 8468e4e6b3..02752f44f8 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -589,7 +589,7 @@ - (UIView *)viewForSelectionAtPoint:(CGPoint)tapPointInWindow // Select in the window that would handle the touch, but don't just use the result of hitTest:withEvent: so we can still select views with interaction disabled. // Default to the the application's key window if none of the windows want the touch. UIWindow *windowForSelection = [UIApplication.sharedApplication keyWindow]; - for (UIWindow *window in [[FLEXUtility allWindows] reverseObjectEnumerator]) { + for (UIWindow *window in [FLEXUtility allWindows].reverseObjectEnumerator) { // Ignore the explorer's own window. if (window != self.view.window) { if ([window hitTest:tapPointInWindow withEvent:nil]) { diff --git a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m index 29b0353d45..2c954f916d 100755 --- a/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m +++ b/Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m @@ -151,7 +151,7 @@ - (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderW return result; }]; if (sortType == FLEXTableColumnHeaderSortTypeDesc) { - NSEnumerator *contentReverseEnumerator = [sortContentData reverseObjectEnumerator]; + NSEnumerator *contentReverseEnumerator = sortContentData.reverseObjectEnumerator; sortContentData = [NSArray arrayWithArray:contentReverseEnumerator.allObjects]; } diff --git a/Classes/ObjectExplorers/Controllers/FLEXDefaultsExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXDefaultsExplorerViewController.m index d189abbf7f..aaf15b2fdf 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXDefaultsExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXDefaultsExplorerViewController.m @@ -48,7 +48,7 @@ - (void)setOnlyShowKeysForAppPrefs:(BOOL)onlyShowKeysForAppPrefs if (onlyShowKeysForAppPrefs) { // Read keys from preferences file - NSString *bundle = [NSBundle mainBundle].bundleIdentifier; + NSString *bundle = NSBundle.mainBundle.bundleIdentifier; NSString *prefsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Preferences"]; NSString *filePath = [NSString stringWithFormat:@"%@/%@.plist", prefsPath, bundle]; self.keys = [NSDictionary dictionaryWithContentsOfFile:filePath].allKeys; diff --git a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m index c9041e2483..dc134bdb32 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXObjectExplorerViewController.m @@ -254,16 +254,6 @@ - (void)updateMetadata return boxedProperties; } -/// Skips NSObject -+ (NSArray *)inheritedPropertiesForClass:(Class)class -{ - NSMutableArray *inheritedProperties = [NSMutableArray array]; - while ((class = [class superclass]) && class != [NSObject class]) { - [inheritedProperties addObjectsFromArray:[self propertiesForClass:class]]; - } - return inheritedProperties; -} - - (void)updateFilteredProperties { NSArray *candidateProperties = [self metadata:FLEXMetadataKindProperties forClassAtIndex:self.selectedScope]; @@ -330,16 +320,6 @@ - (id)valueForPropertyAtIndex:(NSInteger)index return boxedIvars; } -/// Skips NSObject -+ (NSArray *)inheritedIvarsForClass:(Class)class -{ - NSMutableArray *inheritedIvars = [NSMutableArray array]; - while ((class = [class superclass]) && class != [NSObject class]) { - [inheritedIvars addObjectsFromArray:[self ivarsForClass:class]]; - } - return inheritedIvars; -} - - (void)updateFilteredIvars { NSArray *candidateIvars = [self metadata:FLEXMetadataKindIvars forClassAtIndex:self.selectedScope]; @@ -418,16 +398,6 @@ - (void)updateFilteredClassMethods return boxedMethods; } -/// Skips NSObject -+ (NSArray *)inheritedMethodsForClass:(Class)class -{ - NSMutableArray *inheritedMethods = [NSMutableArray array]; - while ((class = [class superclass]) && class != [NSObject class]) { - [inheritedMethods addObjectsFromArray:[self methodsForClass:class]]; - } - return inheritedMethods; -} - - (NSArray *)filteredMethodsFromMethods:(NSArray *)methods areClassMethods:(BOOL)areClassMethods { NSArray *candidateMethods = methods; diff --git a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m index 7fc80296f6..61da586233 100644 --- a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m +++ b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m @@ -106,7 +106,7 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row case FLEXGlobalsRowUserDefaults: return [self explorerViewControllerForObject:[NSUserDefaults standardUserDefaults]]; case FLEXGlobalsRowMainBundle: - return [self explorerViewControllerForObject:[NSBundle mainBundle]]; + return [self explorerViewControllerForObject:NSBundle.mainBundle]; case FLEXGlobalsRowApplication: return [self explorerViewControllerForObject:UIApplication.sharedApplication]; case FLEXGlobalsRowMainScreen: diff --git a/Classes/Utility/FLEXUtility.m b/Classes/Utility/FLEXUtility.m index d718ce9215..ad2d0585d4 100644 --- a/Classes/Utility/FLEXUtility.m +++ b/Classes/Utility/FLEXUtility.m @@ -121,7 +121,7 @@ + (UIColor *)hierarchyIndentPatternColor + (NSString *)applicationImageName { - return [NSBundle mainBundle].executablePath; + return NSBundle.mainBundle.executablePath; } + (NSString *)applicationName @@ -193,7 +193,7 @@ + (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString NSMutableString *mutableString = [originalString mutableCopy]; NSArray *matches = [regex matchesInString:mutableString options:0 range:NSMakeRange(0, mutableString.length)]; - for (NSTextCheckingResult *result in [matches reverseObjectEnumerator]) { + for (NSTextCheckingResult *result in matches.reverseObjectEnumerator) { NSString *foundString = [mutableString substringWithRange:result.range]; NSString *replacementString = escapingDictionary[foundString]; if (replacementString) { @@ -206,7 +206,7 @@ + (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString + (UIInterfaceOrientationMask)infoPlistSupportedInterfaceOrientationsMask { - NSArray *supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]; + NSArray *supportedOrientations = NSBundle.mainBundle.infoDictionary[@"UISupportedInterfaceOrientations"]; UIInterfaceOrientationMask supportedOrientationsMask = 0; if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"]) { supportedOrientationsMask |= UIInterfaceOrientationMaskPortrait; diff --git a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m index c1c6d744f5..c98eeacbad 100644 --- a/Classes/ViewHierarchy/FLEXImagePreviewViewController.m +++ b/Classes/ViewHierarchy/FLEXImagePreviewViewController.m @@ -89,7 +89,7 @@ - (void)actionButtonPressed:(id)sender return; } - NSBundle *mainBundle = [NSBundle mainBundle]; + NSBundle *mainBundle = NSBundle.mainBundle; if ([mainBundle.infoDictionary.allKeys containsObject:@"NSPhotoLibraryUsageDescription"]) { canSaveToCameraRoll = YES; } From 8a5e57c1d27c781c3521852d62a05f3f98311070 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Sat, 14 Sep 2019 15:18:51 -0500 Subject: [PATCH 36/45] Clean up runtime property additions code Macros make the code easier to read and maintain. Also, add -constraints property to UIView. --- .../FLEXViewExplorerViewController.m | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m index d01abd4083..19179ec561 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m @@ -164,29 +164,45 @@ + (UIViewController *)imagePreviewViewControllerForView:(UIView *)view #pragma mark - Runtime Adjustment +#define PropertyKey(suffix) kFLEXPropertyAttributeKey##suffix : @"" +#define PropertyKeyGetter(getter) kFLEXPropertyAttributeKeyCustomGetter : NSStringFromSelector(@selector(getter)) +#define PropertyKeySetter(setter) kFLEXPropertyAttributeKeyCustomSetter : NSStringFromSelector(@selector(setter)) + +#define FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, type, ...) ({ \ + if (@available(iOS iOS_atLeast, *)) { \ + NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithDictionary:@{ \ + kFLEXPropertyAttributeKeyTypeEncoding : @(type), \ + __VA_ARGS__ \ + }]; \ + [FLEXRuntimeUtility \ + tryAddPropertyWithName:#name \ + attributes:attrs \ + toClass:[cls class] \ + ]; \ + } \ +}) +#define FLEXRuntimeUtilityTryAddNonatomicProperty(iOS_atLeast, name, cls, type, ...) \ + FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, @encode(type), PropertyKey(NonAtomic), __VA_ARGS__); +#define FLEXRuntimeUtilityTryAddObjectProperty(iOS_atLeast, name, cls, type, ...) \ + FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, FLEXEncodeClass(type), PropertyKey(NonAtomic), __VA_ARGS__); + + (void)initialize { - // A quirk of UIView: a lot of the "@property"s are not actually properties from the perspective of the runtime. + // A quirk of UIView and some other classes: a lot of the `@property`s are + // not actually properties from the perspective of the runtime. + // // We add these properties to the class at runtime if they haven't been added yet. // This way, we can use our property editor to access and change them. - // The property attributes match the declared attributes in UIView.h - NSDictionary *frameAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(CGRect)), kFLEXUtilityAttributeNonAtomic : @""}; - [FLEXRuntimeUtility tryAddPropertyWithName:"frame" attributes:frameAttributes toClass:[UIView class]]; - - NSDictionary *alphaAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(CGFloat)), kFLEXUtilityAttributeNonAtomic : @""}; - [FLEXRuntimeUtility tryAddPropertyWithName:"alpha" attributes:alphaAttributes toClass:[UIView class]]; - - NSDictionary *clipsAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @""}; - [FLEXRuntimeUtility tryAddPropertyWithName:"clipsToBounds" attributes:clipsAttributes toClass:[UIView class]]; - - NSDictionary *opaqueAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @"", kFLEXUtilityAttributeCustomGetter : @"isOpaque"}; - [FLEXRuntimeUtility tryAddPropertyWithName:"opaque" attributes:opaqueAttributes toClass:[UIView class]]; - - NSDictionary *hiddenAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(@encode(BOOL)), kFLEXUtilityAttributeNonAtomic : @"", kFLEXUtilityAttributeCustomGetter : @"isHidden"}; - [FLEXRuntimeUtility tryAddPropertyWithName:"hidden" attributes:hiddenAttributes toClass:[UIView class]]; - - NSDictionary *backgroundColorAttributes = @{kFLEXUtilityAttributeTypeEncoding : @(FLEXEncodeClass(UIColor)), kFLEXUtilityAttributeNonAtomic : @"", kFLEXUtilityAttributeCopy : @""}; - [FLEXRuntimeUtility tryAddPropertyWithName:"backgroundColor" attributes:backgroundColorAttributes toClass:[UIView class]]; + // The property attributes match the declared attributes in their headers. + + // UIView + FLEXRuntimeUtilityTryAddNonatomicProperty(2, frame, UIView, CGRect); + FLEXRuntimeUtilityTryAddNonatomicProperty(2, alpha, UIView, CGFloat); + FLEXRuntimeUtilityTryAddNonatomicProperty(2, clipsToBounds, UIView, BOOL); + FLEXRuntimeUtilityTryAddNonatomicProperty(2, opaque, UIView, BOOL, PropertyKeyGetter(isOpaque)); + FLEXRuntimeUtilityTryAddNonatomicProperty(2, hidden, UIView, BOOL, PropertyKeyGetter(isHidden)); + FLEXRuntimeUtilityTryAddObjectProperty(2, backgroundColor, UIView, UIColor, PropertyKey(Copy)); + FLEXRuntimeUtilityTryAddObjectProperty(6, constraints, UIView, NSArray, PropertyKey(ReadOnly)); } @end From e30b1854fc6df9dbd0007a83ce88d93acf890671 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Fri, 13 Sep 2019 14:04:42 -0500 Subject: [PATCH 37/45] Fix typos in globals screen - Don't use class names for app delegate or root vc - Reorder some globals rows, also --- .../Globals/FLEXGlobalsTableViewController.m | 21 ++++++-------- .../FLEXObjectExplorerFactory.m | 28 +++++++++---------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m index d1f5dc97c1..3d52b38eee 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsTableViewController.m @@ -74,15 +74,6 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row return [FLEXSystemLogTableViewController flex_concreteGlobalsEntry:row]; case FLEXGlobalsRowNetworkHistory: return [FLEXNetworkHistoryTableViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowRootViewController: - return [FLEXGlobalsEntry - entryWithNameFuture:^NSString *{ - return [NSString stringWithFormat:@"🌴 %@", [s_applicationWindow.rootViewController class]]; - } viewControllerFuture:^UIViewController *{ - UIViewController *rootViewController = s_applicationWindow.rootViewController; - return [FLEXObjectExplorerFactory explorerViewControllerForObject:rootViewController]; - } - ]; case FLEXGlobalsRowKeyWindow: return [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ @@ -91,6 +82,7 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row return [FLEXObjectExplorerFactory explorerViewControllerForObject:s_applicationWindow]; } ]; + case FLEXGlobalsRowRootViewController: case FLEXGlobalsRowProcessInfo: case FLEXGlobalsRowAppDelegate: case FLEXGlobalsRowUserDefaults: @@ -102,7 +94,10 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row return [FLEXObjectExplorerFactory flex_concreteGlobalsEntry:row]; default: - @throw NSInternalInconsistencyException; + @throw [NSException + exceptionWithName:NSInternalInconsistencyException + reason:@"Missing globals case in switch" userInfo:nil + ]; } } @@ -113,15 +108,17 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row dispatch_once(&onceToken, ^{ NSArray *rows = @[ @[ - [self globalsEntryForRow:FLEXGlobalsRowProcessInfo], [self globalsEntryForRow:FLEXGlobalsRowNetworkHistory], [self globalsEntryForRow:FLEXGlobalsRowSystemLog], + [self globalsEntryForRow:FLEXGlobalsRowProcessInfo], [self globalsEntryForRow:FLEXGlobalsRowLiveObjects], [self globalsEntryForRow:FLEXGlobalsRowAddressInspector], [self globalsEntryForRow:FLEXGlobalsRowSystemLibraries], [self globalsEntryForRow:FLEXGlobalsRowAppClasses], ], @[ // FLEXGlobalsSectionAppShortcuts + [self globalsEntryForRow:FLEXGlobalsRowBrowseBundle], + [self globalsEntryForRow:FLEXGlobalsRowBrowseContainer], [self globalsEntryForRow:FLEXGlobalsRowMainBundle], [self globalsEntryForRow:FLEXGlobalsRowUserDefaults], [self globalsEntryForRow:FLEXGlobalsRowAppKeychainItems], @@ -130,8 +127,6 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row [self globalsEntryForRow:FLEXGlobalsRowKeyWindow], [self globalsEntryForRow:FLEXGlobalsRowRootViewController], [self globalsEntryForRow:FLEXGlobalsRowCookies], - [self globalsEntryForRow:FLEXGlobalsRowBrowseBundle], - [self globalsEntryForRow:FLEXGlobalsRowBrowseContainer], ], @[ // FLEXGlobalsSectionMisc [self globalsEntryForRow:FLEXGlobalsRowPasteboard], diff --git a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m index 61da586233..ee026043e7 100644 --- a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m +++ b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m @@ -72,24 +72,24 @@ + (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { switch (row) { - case FLEXGlobalsRowAppDelegate: { - Class cls = [UIApplication.sharedApplication.delegate class]; - return [NSString stringWithFormat:@"👉 %@", cls]; - } + case FLEXGlobalsRowAppDelegate: + return @"👉 App delegate"; + case FLEXGlobalsRowRootViewController: + return @"🌴 Root view controller"; case FLEXGlobalsRowProcessInfo: - return @"🚦 +NSProcessInfo.processInfo"; + return @"🚦 NSProcessInfo.processInfo"; case FLEXGlobalsRowUserDefaults: - return @"💾 +[NSUserDefaults standardUserDefaults]"; + return @"💾 Preferences (NSUserDefaults)"; case FLEXGlobalsRowMainBundle: - return @"📦 +[NSBundle mainBundle]"; + return @"📦 NSBundle.mainBundle"; case FLEXGlobalsRowApplication: - return @"🚀 +UIApplication.sharedApplication"; + return @"🚀 UIApplication.sharedApplication"; case FLEXGlobalsRowMainScreen: - return @"💻 +UIScreen.mainScreen"; + return @"💻 UIScreen.mainScreen"; case FLEXGlobalsRowCurrentDevice: - return @"📱 +[UIDevice currentDevice]"; + return @"📱 UIDevice.currentDevice"; case FLEXGlobalsRowPasteboard: - return @"📋 +UIPasteboard.generalPastboard"; + return @"📋 UIPasteboard.generalPastboard"; default: return nil; } } @@ -102,9 +102,9 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row return [self explorerViewControllerForObject:appDelegate]; } case FLEXGlobalsRowProcessInfo: - return [self explorerViewControllerForObject:NSProcessInfo.processInfo];; + return [self explorerViewControllerForObject:NSProcessInfo.processInfo]; case FLEXGlobalsRowUserDefaults: - return [self explorerViewControllerForObject:[NSUserDefaults standardUserDefaults]]; + return [self explorerViewControllerForObject:NSUserDefaults.standardUserDefaults]; case FLEXGlobalsRowMainBundle: return [self explorerViewControllerForObject:NSBundle.mainBundle]; case FLEXGlobalsRowApplication: @@ -112,7 +112,7 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row case FLEXGlobalsRowMainScreen: return [self explorerViewControllerForObject:UIScreen.mainScreen]; case FLEXGlobalsRowCurrentDevice: - return [self explorerViewControllerForObject:[UIDevice currentDevice]]; + return [self explorerViewControllerForObject:UIDevice.currentDevice]; case FLEXGlobalsRowPasteboard: return [self explorerViewControllerForObject:UIPasteboard.generalPasteboard]; default: return nil; From 46652ac73dac18b780c79fa7b4823fb156d376ee Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Mon, 26 Aug 2019 19:01:00 -0500 Subject: [PATCH 38/45] Improve readability of FLEXRuntimeUtility --- Classes/Utility/FLEXRuntimeUtility.h | 12 ++- Classes/Utility/FLEXRuntimeUtility.m | 116 ++++++++++++++++++++------- 2 files changed, 99 insertions(+), 29 deletions(-) diff --git a/Classes/Utility/FLEXRuntimeUtility.h b/Classes/Utility/FLEXRuntimeUtility.h index 293d02d6d7..898bbf295e 100644 --- a/Classes/Utility/FLEXRuntimeUtility.h +++ b/Classes/Utility/FLEXRuntimeUtility.h @@ -97,11 +97,19 @@ typedef NS_ENUM(char, FLEXTypeEncoding) + (FLEXTypeEncoding *)returnTypeForMethod:(Method)method; // Method Calling/Field Editing -+ (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray *)arguments error:(NSError * __autoreleasing *)error; ++ (id)performSelector:(SEL)selector + onObject:(id)object + withArguments:(NSArray *)arguments + error:(NSError * __autoreleasing *)error; + (NSString *)editableJSONStringForObject:(id)object; + (id)objectValueFromEditableJSONString:(NSString *)string; + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString; -+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock; ++ (void)enumerateTypesInStructEncoding:(const char *)structEncoding + usingBlock:(void (^)(NSString *structName, + const char *fieldTypeEncoding, + NSString *prettyTypeEncoding, + NSUInteger fieldIndex, + NSUInteger fieldOffset))typeBlock; + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type; @end diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index 136318d537..bec380abbc 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -139,7 +139,11 @@ + (SEL)setterSelectorForProperty:(objc_property_t)property NSString *setterSelectorString = [[self attributesDictionaryForProperty:property] objectForKey:kFLEXUtilityAttributeCustomSetter]; if (!setterSelectorString) { NSString *propertyName = @(property_getName(property)); - setterSelectorString = [NSString stringWithFormat:@"set%@%@:", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]]; + setterSelectorString = [NSString + stringWithFormat:@"set%@%@:", + [propertyName substringToIndex:1].uppercaseString, + [propertyName substringFromIndex:1] + ]; } if (setterSelectorString) { setterSelector = NSSelectorFromString(setterSelectorString); @@ -248,7 +252,9 @@ + (NSString *)descriptionForIvarOrPropertyValue:(id)value return description; } -+ (void)tryAddPropertyWithName:(const char *)name attributes:(NSDictionary *)attributePairs toClass:(__unsafe_unretained Class)theClass ++ (void)tryAddPropertyWithName:(const char *)name + attributes:(NSDictionary *)attributePairs + toClass:(__unsafe_unretained Class)theClass { objc_property_t property = class_getProperty(theClass, name); if (!property) { @@ -313,13 +319,18 @@ + (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object NSValue *valueValue = (NSValue *)value; // Make sure that the box contained the correct type. - NSAssert(strcmp([valueValue objCType], typeEncodingCString) == 0, @"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %s on object: %@", [valueValue objCType], typeEncodingCString, ivar_getName(ivar), object); + NSAssert( + strcmp(valueValue.objCType, typeEncodingCString) == 0, + @"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %s on object: %@", + valueValue.objCType, typeEncodingCString, ivar_getName(ivar), object + ); NSUInteger bufferSize = 0; @try { // NSGetSizeAndAlignment barfs on type encoding for bitfields. NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL); } @catch (NSException *exception) { } + if (bufferSize > 0) { void *buffer = calloc(bufferSize, 1); [valueValue getValue:buffer]; @@ -372,7 +383,11 @@ + (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMeth char *argType = method_copyArgumentType(method, argIndex + kFLEXNumberOfImplicitArgs); NSString *readableArgType = (argType != NULL) ? [self readableTypeForEncoding:@(argType)] : nil; free(argType); - NSString *prettyComponent = [NSString stringWithFormat:@"%@:(%@) ", [selectorComponents objectAtIndex:argIndex], readableArgType]; + NSString *prettyComponent = [NSString + stringWithFormat:@"%@:(%@) ", + selectorComponents[argIndex], + readableArgType + ]; [components addObject:prettyComponent]; } @@ -387,13 +402,24 @@ + (FLEXTypeEncoding *)returnTypeForMethod:(Method)method #pragma mark - Method Calling/Field Editing (Public) -+ (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray *)arguments error:(NSError * __autoreleasing *)error ++ (id)performSelector:(SEL)selector + onObject:(id)object + withArguments:(NSArray *)arguments + error:(NSError * __autoreleasing *)error { // Bail if the object won't respond to this selector. if (![object respondsToSelector:selector]) { if (error) { - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"%@ does not respond to the selector %@", object, NSStringFromSelector(selector)]}; - *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector userInfo:userInfo]; + NSString *msg = [NSString + stringWithFormat:@"%@ does not respond to the selector %@", + object, NSStringFromSelector(selector) + ]; + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : msg }; + *error = [NSError + errorWithDomain:FLEXRuntimeUtilityErrorDomain + code:FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector + userInfo:userInfo + ]; } return nil; } @@ -424,13 +450,17 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs; id argumentObject = arguments.count > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil; - // NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil. + // NSNull in the arguments array can be passed as a placeholder to indicate nil. + // We only need to set the argument if it will be non-nil. if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) { const char *typeEncodingCString = [methodSignature getArgumentTypeAtIndex:argumentIndex]; - if (typeEncodingCString[0] == FLEXTypeEncodingObjcObject || typeEncodingCString[0] == FLEXTypeEncodingObjcClass || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { + if (typeEncodingCString[0] == FLEXTypeEncodingObjcObject || + typeEncodingCString[0] == FLEXTypeEncodingObjcClass || + [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { // Object [invocation setArgument:&argumentObject atIndex:argumentIndex]; - } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 && [argumentObject isKindOfClass:[UIColor class]]) { + } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 && + [argumentObject isKindOfClass:[UIColor class]]) { // Bridging UIColor to CGColorRef CGColorRef colorRef = [argumentObject CGColor]; [invocation setArgument:&colorRef atIndex:argumentIndex]; @@ -441,8 +471,17 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * // Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature if (strcmp([argumentValue objCType], typeEncodingCString) != 0) { if (error) { - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Type encoding mismatch for argument at index %lu. Value type: %s; Method argument type: %s.", (unsigned long)argumentsArrayIndex, [argumentValue objCType], typeEncodingCString]}; - *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch userInfo:userInfo]; + NSString *msg = [NSString + stringWithFormat:@"Type encoding mismatch for argument at index %lu. " + "Value type: %s; Method argument type: %s.", + (unsigned long)argumentsArrayIndex, argumentValue.objCType, typeEncodingCString + ]; + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : msg }; + *error = [NSError + errorWithDomain:FLEXRuntimeUtilityErrorDomain + code:FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch + userInfo:userInfo + ]; } return nil; } @@ -494,11 +533,10 @@ + (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray * NSString *class = NSStringFromClass([object class]); NSString *calledOn = object == [object class] ? class : [@"an instance of " stringByAppendingString:class]; - NSString *message = [NSString stringWithFormat:@"Exception '%@' thrown while performing selector '%@' on %@.\nReason:\n\n%@", - exception.name, - NSStringFromSelector(selector), - calledOn, - exception.reason]; + NSString *message = [NSString + stringWithFormat:@"Exception '%@' thrown while performing selector '%@' on %@.\nReason:\n\n%@", + exception.name, NSStringFromSelector(selector), calledOn, exception.reason + ]; *error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain code:FLEXRuntimeUtilityErrorCodeInvocationFailed @@ -557,7 +595,8 @@ + (NSString *)editableJSONStringForObject:(id)object // We always wrap the object inside an array and then strip the outer square braces off the final string. NSArray *wrappedObject = @[object]; if ([NSJSONSerialization isValidJSONObject:wrappedObject]) { - NSString *wrappedDescription = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL] encoding:NSUTF8StringEncoding]; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL]; + NSString *wrappedDescription = [NSString stringWithUTF8String:jsonData.bytes]; editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, wrappedDescription.length - 2)]; } } @@ -569,8 +608,12 @@ + (id)objectValueFromEditableJSONString:(NSString *)string { id value = nil; // nil for empty string/whitespace - if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] > 0) { - value = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:NULL]; + if ([string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length) { + value = [NSJSONSerialization + JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] + options:NSJSONReadingAllowFragments + error:NULL + ]; } return value; } @@ -627,13 +670,20 @@ + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputStri return value; } -+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock ++ (void)enumerateTypesInStructEncoding:(const char *)structEncoding + usingBlock:(void (^)(NSString *structName, + const char *fieldTypeEncoding, + NSString *prettyTypeEncoding, + NSUInteger fieldIndex, + NSUInteger fieldOffset))typeBlock { if (structEncoding && structEncoding[0] == FLEXTypeEncodingStructBegin) { const char *equals = strchr(structEncoding, '='); if (equals) { const char *nameStart = structEncoding + 1; - NSString *structName = [@(structEncoding) substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)]; + NSString *structName = [@(structEncoding) + substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart) + ]; NSUInteger fieldAlignment = 0; NSUInteger structSize = 0; @@ -650,14 +700,22 @@ + (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:( NSUInteger fieldSize = 0; // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here. const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL); - NSString *typeEncoding = [@(structEncoding) substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)]; + NSString *typeEncoding = [@(structEncoding) + substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart) + ]; // Padding to keep proper alignment. __attribute((packed)) structs will break here. // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those. const NSUInteger currentSizeSum = runningFieldOffset % fieldAlignment; if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) { runningFieldOffset += fieldAlignment - currentSizeSum; } - typeBlock(structName, typeEncoding.UTF8String, [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset); + typeBlock( + structName, + typeEncoding.UTF8String, + [self readableTypeForEncoding:typeEncoding], + runningFieldIndex, + runningFieldOffset + ); runningFieldOffset += fieldSize; runningFieldIndex++; typeStart = nextTypeStart; @@ -712,7 +770,9 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString // According to https://github.com/nygard/class-dump/commit/33fb5ed221810685f57c192e1ce8ab6054949a7c, // there are some consecutive quoted strings, so use `_` to concatenate the names. NSString *const fieldNamesString = [encodingString substringWithRange:NSMakeRange(0, fieldNameOffset)]; - NSArray *const fieldNames = [fieldNamesString componentsSeparatedByString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote]]; + NSArray *const fieldNames = [fieldNamesString + componentsSeparatedByString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote] + ]; NSMutableString *finalFieldNamesString = [NSMutableString string]; for (NSString *const fieldName in fieldNames) { if (fieldName.length > 0) { @@ -729,7 +789,7 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString // Objects if (encodingCString[0] == FLEXTypeEncodingObjcObject) { NSString *class = [encodingString substringFromIndex:1]; - class = [class stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote] withString:@""]; + class = [class stringByReplacingOccurrencesOfString:@"\"" withString:@""]; if (class.length == 0 || (class.length == 1 && [class characterAtIndex:0] == FLEXTypeEncodingUnknown)) { class = @"id"; } else { @@ -821,7 +881,9 @@ + (NSString *)readableTypeForEncoding:(NSString *)encodingString if (nameStart[0] == FLEXTypeEncodingUnknown) { return @"anonymous struct"; } else { - NSString *const structName = [encodingString substringWithRange:NSMakeRange(nameStart - encodingCString, equals - nameStart)]; + NSString *const structName = [encodingString + substringWithRange:NSMakeRange(nameStart - encodingCString, equals - nameStart) + ]; return structName; } } From f64e6ec3c9d992071c51265dfb6e6338638cfd59 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Mon, 26 Aug 2019 14:57:59 -0500 Subject: [PATCH 39/45] Rename tests target --- FLEX.xcodeproj/project.pbxproj | 26 +++++++++---------- .../FLEXTestsMethodsList.m | 0 .../Info.plist | 0 3 files changed, 13 insertions(+), 13 deletions(-) rename {FLEXTestsMethodsList => FLEXTests}/FLEXTestsMethodsList.m (100%) rename {FLEXTestsMethodsList => FLEXTests}/Info.plist (100%) diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 5105572a80..dfb8bf9b5d 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -223,7 +223,7 @@ /* Begin PBXFileReference section */ 04F1CA181C137CF1000A52B0 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FLEXTestsMethodsList.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1C27A8B61F0E5A0300F0D02D /* FLEXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FLEXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTestsMethodsList.m; sourceTree = ""; }; 1C27A8BA1F0E5A0400F0D02D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 222C88211C7339DC007CA15F /* FLEXRealmDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDefines.h; sourceTree = ""; }; @@ -452,20 +452,20 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1C27A8B71F0E5A0400F0D02D /* FLEXTestsMethodsList */ = { + 1C27A8B71F0E5A0400F0D02D /* FLEXTests */ = { isa = PBXGroup; children = ( 1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */, 1C27A8BA1F0E5A0400F0D02D /* Info.plist */, ); - path = FLEXTestsMethodsList; + path = FLEXTests; sourceTree = ""; }; 3A4C94151B5B20570088C3F2 = { isa = PBXGroup; children = ( 3A4C94211B5B20570088C3F2 /* FLEX */, - 1C27A8B71F0E5A0400F0D02D /* FLEXTestsMethodsList */, + 1C27A8B71F0E5A0400F0D02D /* FLEXTests */, 3A4C95451B5B216C0088C3F2 /* Frameworks */, 3A4C94201B5B20570088C3F2 /* Products */, ); @@ -475,7 +475,7 @@ isa = PBXGroup; children = ( 3A4C941F1B5B20570088C3F2 /* FLEX.framework */, - 1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */, + 1C27A8B61F0E5A0300F0D02D /* FLEXTests.xctest */, ); name = Products; sourceTree = ""; @@ -980,9 +980,9 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 1C27A8B51F0E5A0300F0D02D /* FLEXTestsMethodsList */ = { + 1C27A8B51F0E5A0300F0D02D /* FLEXTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTestsMethodsList" */; + buildConfigurationList = 1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTests" */; buildPhases = ( 1C27A8B21F0E5A0300F0D02D /* Sources */, 1C27A8B31F0E5A0300F0D02D /* Frameworks */, @@ -993,9 +993,9 @@ dependencies = ( 1C27A8BD1F0E5A0400F0D02D /* PBXTargetDependency */, ); - name = FLEXTestsMethodsList; + name = FLEXTests; productName = FLEXTestsMethodsList; - productReference = 1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */; + productReference = 1C27A8B61F0E5A0300F0D02D /* FLEXTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 3A4C941E1B5B20570088C3F2 /* FLEX */ = { @@ -1049,7 +1049,7 @@ projectRoot = ""; targets = ( 3A4C941E1B5B20570088C3F2 /* FLEX */, - 1C27A8B51F0E5A0300F0D02D /* FLEXTestsMethodsList */, + 1C27A8B51F0E5A0300F0D02D /* FLEXTests */, ); }; /* End PBXProject section */ @@ -1203,7 +1203,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = U3LST7M92S; - INFOPLIST_FILE = FLEXTestsMethodsList/Info.plist; + INFOPLIST_FILE = FLEXTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEXTestsMethodsList; @@ -1218,7 +1218,7 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; DEVELOPMENT_TEAM = U3LST7M92S; - INFOPLIST_FILE = FLEXTestsMethodsList/Info.plist; + INFOPLIST_FILE = FLEXTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEXTestsMethodsList; @@ -1398,7 +1398,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTestsMethodsList" */ = { + 1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 1C27A8BE1F0E5A0400F0D02D /* Debug */, diff --git a/FLEXTestsMethodsList/FLEXTestsMethodsList.m b/FLEXTests/FLEXTestsMethodsList.m similarity index 100% rename from FLEXTestsMethodsList/FLEXTestsMethodsList.m rename to FLEXTests/FLEXTestsMethodsList.m diff --git a/FLEXTestsMethodsList/Info.plist b/FLEXTests/Info.plist similarity index 100% rename from FLEXTestsMethodsList/Info.plist rename to FLEXTests/Info.plist From 0803b46f9d5616bd569e8f6e9274d9d0310e7854 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Sun, 15 Sep 2019 12:03:09 -0500 Subject: [PATCH 40/45] Fix #329 Whoops. Thanks @DGh0st Also fix a build issue, a typo in some macros --- .../Controllers/FLEXViewExplorerViewController.m | 8 ++++---- Classes/Utility/FLEXRuntimeUtility.m | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m b/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m index 19179ec561..0ab396a6e4 100644 --- a/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m +++ b/Classes/ObjectExplorers/Controllers/FLEXViewExplorerViewController.m @@ -164,14 +164,14 @@ + (UIViewController *)imagePreviewViewControllerForView:(UIView *)view #pragma mark - Runtime Adjustment -#define PropertyKey(suffix) kFLEXPropertyAttributeKey##suffix : @"" -#define PropertyKeyGetter(getter) kFLEXPropertyAttributeKeyCustomGetter : NSStringFromSelector(@selector(getter)) -#define PropertyKeySetter(setter) kFLEXPropertyAttributeKeyCustomSetter : NSStringFromSelector(@selector(setter)) +#define PropertyKey(suffix) kFLEXUtilityAttribute##suffix : @"" +#define PropertyKeyGetter(getter) kFLEXUtilityAttributeCustomGetter : NSStringFromSelector(@selector(getter)) +#define PropertyKeySetter(setter) kFLEXUtilityAttributeCustomSetter : NSStringFromSelector(@selector(setter)) #define FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, type, ...) ({ \ if (@available(iOS iOS_atLeast, *)) { \ NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithDictionary:@{ \ - kFLEXPropertyAttributeKeyTypeEncoding : @(type), \ + kFLEXUtilityAttributeTypeEncoding : @(type), \ __VA_ARGS__ \ }]; \ [FLEXRuntimeUtility \ diff --git a/Classes/Utility/FLEXRuntimeUtility.m b/Classes/Utility/FLEXRuntimeUtility.m index bec380abbc..4a61077fb7 100644 --- a/Classes/Utility/FLEXRuntimeUtility.m +++ b/Classes/Utility/FLEXRuntimeUtility.m @@ -434,7 +434,8 @@ + (id)performSelector:(SEL)selector // // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector)); NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector]; - if (!methodSignature.methodReturnLength) { + if (!methodSignature.methodReturnLength && + methodSignature.methodReturnType[0] != FLEXTypeEncodingVoid) { return nil; } @@ -493,10 +494,9 @@ + (id)performSelector:(SEL)selector NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL); if (bufferSize > 0) { - void *buffer = calloc(bufferSize, 1); + void *buffer = alloca(bufferSize); [argumentValue getValue:buffer]; [invocation setArgument:buffer atIndex:argumentIndex]; - free(buffer); } } @catch (NSException *exception) { } } @@ -506,6 +506,7 @@ + (id)performSelector:(SEL)selector // Try to invoke the invocation but guard against an exception being thrown. id returnObject = nil; @try { + [invocation invoke]; // Retrieve the return value and box if necessary. const char *returnType = methodSignature.methodReturnType; From a78bf1b22fc2ee66d330c5205161211435b0681e Mon Sep 17 00:00:00 2001 From: LAgagggggg <15807814960@163.com> Date: Wed, 2 Oct 2019 23:29:54 +0800 Subject: [PATCH 41/45] Fix crash during NSURLSession's resume --- Classes/Network/PonyDebugger/FLEXNetworkObserver.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m index 34909571da..e842a432bb 100644 --- a/Classes/Network/PonyDebugger/FLEXNetworkObserver.m +++ b/Classes/Network/PonyDebugger/FLEXNetworkObserver.m @@ -293,6 +293,14 @@ + (void)injectIntoNSURLSessionTaskResume Method originalResume = class_getInstanceMethod(class, selector); void (^swizzleBlock)(NSURLSessionTask *) = ^(NSURLSessionTask *slf) { + + // iOS's internal HTTP parser finalization code is mysteriously not thread safe, + // invoke it asynchronously has a chance to cause a `double free` crash. + // This line below will ask for HTTPBody synchronously, make the HTTPParser parse the request and cache them in advance, + // After that the HTTPParser will be finalized, + // make sure other threads inspecting the request won't trigger a race to finalize the parser. + [slf.currentRequest HTTPBody]; + [[FLEXNetworkObserver sharedObserver] URLSessionTaskWillResume:slf]; ((void(*)(id, SEL))objc_msgSend)(slf, swizzledSelector); }; From 53538bfeadc11bafca57de291afed6f9dba73571 Mon Sep 17 00:00:00 2001 From: Elfred Pagan Date: Fri, 11 Oct 2019 13:21:30 -0700 Subject: [PATCH 42/45] Add context menu to file browser in iOS 13. The current implementation is deprecated, which limits the functionality of the file browser. --- .../FLEXFileBrowserTableViewController.m | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m index e074cca948..3cf95aa0c0 100644 --- a/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m +++ b/Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserTableViewController.m @@ -305,6 +305,45 @@ - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtInd // Since our actions are outside of that protocol, we need to manually handle the action forwarding from the cells. } +#if FLEX_AT_LEAST_IOS13_SDK + +- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) +{ + __weak typeof(self) weakSelf = self; + return [UIContextMenuConfiguration configurationWithIdentifier:NSUUID.UUID.UUIDString + previewProvider:nil + actionProvider:^UIMenu * _Nullable(NSArray * _Nonnull suggestedActions) { + UITableViewCell * const cell = [tableView cellForRowAtIndexPath:indexPath]; + UIAction *rename = [UIAction actionWithTitle:@"Rename" + image:nil + identifier:@"Rename" + handler:^(__kindof UIAction * _Nonnull action) { + [weakSelf fileBrowserRename:cell]; + }]; + UIAction *delete = [UIAction actionWithTitle:@"Delete" + image:nil + identifier:@"Delete" + handler:^(__kindof UIAction * _Nonnull action) { + [weakSelf fileBrowserDelete:cell]; + }]; + UIAction *copyPath = [UIAction actionWithTitle:@"Copy Path" + image:nil + identifier:@"Copy Path" + handler:^(__kindof UIAction * _Nonnull action) { + [weakSelf fileBrowserCopyPath:cell]; + }]; + UIAction *share = [UIAction actionWithTitle:@"Share" + image:nil + identifier:@"Share" + handler:^(__kindof UIAction * _Nonnull action) { + [weakSelf fileBrowserShare:cell]; + }]; + return [UIMenu menuWithTitle:@"Manage File" image:nil identifier:@"Manage File" options:UIMenuOptionsDisplayInline children:@[rename, delete, copyPath, share]]; + }]; +} + +#endif + - (void)openFileController:(NSString *)fullPath { UIDocumentInteractionController *controller = [UIDocumentInteractionController new]; From 226e0cd80324e7bed1d524334c2befff6b775b99 Mon Sep 17 00:00:00 2001 From: Tanner Bennett Date: Sat, 26 Oct 2019 15:55:41 -0500 Subject: [PATCH 43/45] Update to recommended project settings --- .../xcshareddata/xcschemes/UICatalog.xcscheme | 2 +- FLEX.xcodeproj/project.pbxproj | 6 +++--- FLEX.xcodeproj/xcshareddata/xcschemes/FLEX.xcscheme | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme b/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme index 2f56d0c1a4..9197da1dd4 100644 --- a/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme +++ b/Example/UICatalog.xcodeproj/xcshareddata/xcschemes/UICatalog.xcscheme @@ -1,6 +1,6 @@ Date: Fri, 8 Nov 2019 18:12:36 +0100 Subject: [PATCH 44/45] Address "This block declaration is not a prototype" warning (#345) Thanks @jnavarrom --- Classes/Core/FLEXScopeCarousel.m | 2 +- Classes/Core/FLEXTableViewController.h | 2 +- Classes/Core/FLEXTableViewController.m | 4 ++-- Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m | 2 +- Classes/Utility/FLEXAlert.h | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Classes/Core/FLEXScopeCarousel.m b/Classes/Core/FLEXScopeCarousel.m index 43bbdb26eb..f7743c8760 100644 --- a/Classes/Core/FLEXScopeCarousel.m +++ b/Classes/Core/FLEXScopeCarousel.m @@ -76,7 +76,7 @@ - (id)initWithFrame:(CGRect)frame { // Notify observers __typeof(self) self = weakSelf; - for (void (^block)() in self.dynamicTypeHandlers) { + for (void (^block)(FLEXScopeCarousel *) in self.dynamicTypeHandlers) { block(self); } } diff --git a/Classes/Core/FLEXTableViewController.h b/Classes/Core/FLEXTableViewController.h index 561f68ae4b..368e7e8765 100644 --- a/Classes/Core/FLEXTableViewController.h +++ b/Classes/Core/FLEXTableViewController.h @@ -89,6 +89,6 @@ extern CGFloat const kFLEXDebounceForExpensiveIO; /// Convenient for doing some async processor-intensive searching /// in the background before updating the UI back on the main queue. -- (void)onBackgroundQueue:(NSArray *(^)())backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock; +- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock; @end diff --git a/Classes/Core/FLEXTableViewController.m b/Classes/Core/FLEXTableViewController.m index 9a50b0f093..f75487244f 100644 --- a/Classes/Core/FLEXTableViewController.m +++ b/Classes/Core/FLEXTableViewController.m @@ -127,7 +127,7 @@ - (void)setAutomaticallyShowsSearchBarCancelButton:(BOOL)autoShowCancel { - (void)updateSearchResults:(NSString *)newText { } -- (void)onBackgroundQueue:(NSArray *(^)())backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock { +- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSArray *items = backgroundBlock(); dispatch_async(dispatch_get_main_queue(), ^{ @@ -173,7 +173,7 @@ - (void)viewDidDisappear:(BOOL)animated { #pragma mark - Private -- (void)debounce:(void(^)())block { +- (void)debounce:(void(^)(void))block { [self.debounceTimer invalidate]; self.debounceTimer = [NSTimer diff --git a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m index 6d88b45b4c..6b6025cd0b 100644 --- a/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m +++ b/Classes/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m @@ -182,7 +182,7 @@ - (NSString *)password { #ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE + (BOOL)isSynchronizationAvailable { #if TARGET_OS_IPHONE - return @available(iOS 7.0, *); + return YES; #else return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; #endif diff --git a/Classes/Utility/FLEXAlert.h b/Classes/Utility/FLEXAlert.h index fd38704510..4b42d7728a 100644 --- a/Classes/Utility/FLEXAlert.h +++ b/Classes/Utility/FLEXAlert.h @@ -10,14 +10,14 @@ @class FLEXAlert, FLEXAlertAction; -typedef void (^FLEXAlertReveal)(); +typedef void (^FLEXAlertReveal)(void); typedef void (^FLEXAlertBuilder)(FLEXAlert *make); typedef FLEXAlert *(^FLEXAlertStringProperty)(NSString *); typedef FLEXAlert *(^FLEXAlertStringArg)(NSString *); typedef FLEXAlert *(^FLEXAlertTextField)(void(^configurationHandler)(UITextField *textField)); typedef FLEXAlertAction *(^FLEXAlertAddAction)(NSString *title); typedef FLEXAlertAction *(^FLEXAlertActionStringProperty)(NSString *); -typedef FLEXAlertAction *(^FLEXAlertActionProperty)(); +typedef FLEXAlertAction *(^FLEXAlertActionProperty)(void); typedef FLEXAlertAction *(^FLEXAlertActionBOOLProperty)(BOOL); typedef FLEXAlertAction *(^FLEXAlertActionHandler)(void(^handler)(NSArray *strings)); From a6cbfbd3fd988c271449004ef267aa32c6a4346e Mon Sep 17 00:00:00 2001 From: GGLGeek <11263880+gl-lei@users.noreply.github.com> Date: Sat, 9 Nov 2019 03:01:32 +0800 Subject: [PATCH 45/45] Fix stack memory being used in async block (#344) --- Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m index 9548957595..4f9441f93b 100644 --- a/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m +++ b/Classes/GlobalStateExplorers/SystemLog/FLEXOSLogController.m @@ -178,9 +178,11 @@ - (BOOL)handleStreamEntry:(os_activity_stream_entry_t)entry error:(int)error { if (entry->log_message.format && !(strcmp(entry->log_message.format, messageText))) { messageText = (char *)entry->log_message.format; } + // move messageText from stack to heap + NSString *msg = [NSString stringWithUTF8String:messageText]; dispatch_async(dispatch_get_main_queue(), ^{ - FLEXSystemLogMessage *message = [FLEXSystemLogMessage logMessageFromDate:date text:@(messageText)]; + FLEXSystemLogMessage *message = [FLEXSystemLogMessage logMessageFromDate:date text:msg]; if (self.persistent) { [self.messages addObject:message]; }