From 543c93b0edb1ccc561a520bd6a249d672c13e3e0 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 5 Dec 2015 13:25:45 -0800 Subject: [PATCH] Add enable multiple selection option; Update test cases. --- DLRadioButton/DLRadioButton.h | 22 ++++-- DLRadioButton/DLRadioButton.m | 50 ++++++++++--- .../project.pbxproj | 7 +- .../DLDemoViewController.h | 3 + .../DLDemoViewController.m | 8 +- .../DLRadioButtonExample-Info.plist | 2 +- .../DLRadioButtonExample/iPhone.storyboard | 74 ++++++++++--------- .../DLRadioButtonExampleTests-Info.plist | 2 +- .../DLRadioButtonExampleTests.m | 28 +++++++ 9 files changed, 140 insertions(+), 56 deletions(-) diff --git a/DLRadioButton/DLRadioButton.h b/DLRadioButton/DLRadioButton.h index dd17d17..df84146 100644 --- a/DLRadioButton/DLRadioButton.h +++ b/DLRadioButton/DLRadioButton.h @@ -43,14 +43,14 @@ IB_DESIGNABLE @property (nonatomic) IBInspectable CGFloat marginWidth; /** - Whether icon on the right side. + Whether icon on the right side, default is NO. */ -@property (nonatomic) IBInspectable BOOL isIconOnRight; +@property (nonatomic, getter=isIconOnRight) IBInspectable BOOL iconOnRight; /** - Whether use square icon. + Whether use square icon, default is NO. */ -@property (nonatomic) IBInspectable BOOL isIconSquare; +@property (nonatomic, getter=isIconSquare) IBInspectable BOOL iconSquare; /** Image for radio button icon (optional). @@ -63,12 +63,22 @@ IB_DESIGNABLE @property (nonatomic) IBInspectable UIImage *iconSelected; /** - @return Current selected button in same group. + Whether enable multiple selection, default is NO. + */ +@property (nonatomic, getter=isMultipleSelectionEnabled) BOOL multipleSelectionEnabled; + +/** + @return Selected button in same group. */ - (DLRadioButton *)selectedButton; /** - Clear selection for other buttons in in same group. + @return Selected buttons in same group, use it only if multiple selection is enabled. + */ +- (NSArray *)selectedButtons; + +/** + Clears selection for other buttons in in same group. */ - (void)deselectOtherButtons; diff --git a/DLRadioButton/DLRadioButton.m b/DLRadioButton/DLRadioButton.m index a1c3c52..84ad159 100644 --- a/DLRadioButton/DLRadioButton.m +++ b/DLRadioButton/DLRadioButton.m @@ -37,6 +37,17 @@ - (void)setIconSelected:(UIImage *)iconSelected { [self setImage:self.iconSelected forState:UIControlStateSelected | UIControlStateHighlighted]; } +- (void)setMultipleSelectionEnabled:(BOOL)multipleSelectionEnabled { + if (!self.isChaining) { + self.isChaining = YES; + _multipleSelectionEnabled = multipleSelectionEnabled; + for (DLRadioButton *radioButton in self.otherButtons) { + radioButton.multipleSelectionEnabled = multipleSelectionEnabled; + } + self.isChaining = NO; + } +} + #pragma mark - Helpers - (void)drawButton { @@ -125,16 +136,31 @@ - (void)deselectOtherButtons { } - (DLRadioButton *)selectedButton { - if (self.selected) { - return self; - } else { - for (DLRadioButton *radioButton in self.otherButtons) { - if (radioButton.selected) { - return radioButton; + if (!self.isMultipleSelectionEnabled) { + if (self.selected) { + return self; + } else { + for (DLRadioButton *radioButton in self.otherButtons) { + if (radioButton.selected) { + return radioButton; + } } } - return nil; } + return nil; +} + +- (NSArray *)selectedButtons { + NSMutableArray *selectedButtons = [[NSMutableArray alloc] init]; + if (self.selected) { + [selectedButtons addObject:self]; + } + for (DLRadioButton *radioButton in self.otherButtons) { + if (radioButton.selected) { + [selectedButtons addObject:radioButton]; + } + } + return selectedButtons; } #pragma mark - UIButton @@ -158,9 +184,13 @@ - (UIColor *)titleColorForState:(UIControlState)state { #pragma mark - UIControl - (void)setSelected:(BOOL)selected { - [super setSelected:selected]; - if (selected) { - [self deselectOtherButtons]; + if (self.isMultipleSelectionEnabled) { + [super setSelected:!self.isSelected]; + } else { + [super setSelected:selected]; + if (selected) { + [self deselectOtherButtons]; + } } } diff --git a/DLRadioButtonExample/DLRadioButtonExample.xcodeproj/project.pbxproj b/DLRadioButtonExample/DLRadioButtonExample.xcodeproj/project.pbxproj index 1cc0da5..d2e36fd 100644 --- a/DLRadioButtonExample/DLRadioButtonExample.xcodeproj/project.pbxproj +++ b/DLRadioButtonExample/DLRadioButtonExample.xcodeproj/project.pbxproj @@ -211,7 +211,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = DL; - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Xingruo Liu"; TargetAttributes = { D1BE39FE19A7D263004BD3F5 = { @@ -334,6 +334,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -399,6 +400,7 @@ GCC_PREFIX_HEADER = "DLRadioButtonExample/DLRadioButtonExample-Prefix.pch"; INFOPLIST_FILE = "DLRadioButtonExample/DLRadioButtonExample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.liuxingruo.$(PRODUCT_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; @@ -416,6 +418,7 @@ GCC_PREFIX_HEADER = "DLRadioButtonExample/DLRadioButtonExample-Prefix.pch"; INFOPLIST_FILE = "DLRadioButtonExample/DLRadioButtonExample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.liuxingruo.$(PRODUCT_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; @@ -438,6 +441,7 @@ "$(inherited)", ); INFOPLIST_FILE = "DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.liuxingruo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -456,6 +460,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "DLRadioButtonExample/DLRadioButtonExample-Prefix.pch"; INFOPLIST_FILE = "DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.liuxingruo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; diff --git a/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.h b/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.h index ac0c7e6..63d3d91 100644 --- a/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.h +++ b/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.h @@ -1,5 +1,8 @@ #import +#import "DLRadioButton.h" @interface DLDemoViewController : UIViewController +@property (weak, nonatomic) IBOutlet DLRadioButton *waterButton; + @end diff --git a/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.m b/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.m index 3165636..fb4ae97 100644 --- a/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.m +++ b/DLRadioButtonExample/DLRadioButtonExample/DLDemoViewController.m @@ -1,5 +1,4 @@ #import "DLDemoViewController.h" -#import "DLRadioButton.h" @implementation DLDemoViewController @@ -14,6 +13,9 @@ - (IBAction)logSelectedButton:(DLRadioButton *)radiobutton { - (void)viewDidLoad { [super viewDidLoad]; + // enable multiple selection for water, beer and wine buttons. + self.waterButton.multipleSelectionEnabled = YES; + // programmatically add buttons // first button DLRadioButton *firstRadioButton = [[DLRadioButton alloc] initWithFrame:CGRectMake(30, 350, self.view.frame.size.width - 60, 15)]; @@ -40,11 +42,11 @@ - (void)viewDidLoad { radioButton.iconColor = buttonColor; radioButton.indicatorColor = buttonColor; if (i % 2 == 0) { - radioButton.isIconSquare = YES; + radioButton.iconSquare = YES; } if (i > 0) { // put icon on the right side - radioButton.isIconOnRight = YES; + radioButton.iconOnRight = YES; radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; } else { radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; diff --git a/DLRadioButtonExample/DLRadioButtonExample/DLRadioButtonExample-Info.plist b/DLRadioButtonExample/DLRadioButtonExample/DLRadioButtonExample-Info.plist index 4f98614..d853cea 100644 --- a/DLRadioButtonExample/DLRadioButtonExample/DLRadioButtonExample-Info.plist +++ b/DLRadioButtonExample/DLRadioButtonExample/DLRadioButtonExample-Info.plist @@ -9,7 +9,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.liuxingruo.$(PRODUCT_NAME) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/DLRadioButtonExample/DLRadioButtonExample/iPhone.storyboard b/DLRadioButtonExample/DLRadioButtonExample/iPhone.storyboard index 24e88dc..400a4b0 100644 --- a/DLRadioButtonExample/DLRadioButtonExample/iPhone.storyboard +++ b/DLRadioButtonExample/DLRadioButtonExample/iPhone.storyboard @@ -1,8 +1,8 @@ - + - + @@ -19,12 +19,14 @@ - - + + + + + @@ -245,9 +256,4 @@ - - - - - diff --git a/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist b/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist index 26fa2a7..169b6f7 100644 --- a/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist +++ b/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.liuxingruo.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests.m b/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests.m index 546b5dc..623ae3c 100644 --- a/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests.m +++ b/DLRadioButtonExample/DLRadioButtonExampleTests/DLRadioButtonExampleTests.m @@ -29,8 +29,13 @@ - (void)tearDown { - (void)testButtonSelection { [self.firstButton sendActionsForControlEvents:UIControlEventTouchUpInside]; [self.secondButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + + // selected button should be second button. XCTAssertEqualObjects([self.firstButton selectedButton], self.secondButton); XCTAssertEqualObjects([self.secondButton selectedButton], self.secondButton); + XCTAssertEqualObjects([self.thirdButton selectedButton], self.secondButton); + + // selected button should be third button. [self.thirdButton sendActionsForControlEvents:UIControlEventTouchUpInside]; XCTAssertEqualObjects([self.secondButton selectedButton], self.thirdButton); } @@ -41,4 +46,27 @@ - (void)testButtonDeselection { XCTAssertNil([self.firstButton selectedButton]); } +- (void)testMultipleButtonsSelection { + self.firstButton.multipleSelectionEnabled = YES; + [self.secondButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + [self.thirdButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + + // selected button should return nil, once multiple selection enabled. + XCTAssertNil([self.firstButton selectedButton]); + XCTAssertNil([self.secondButton selectedButton]); + XCTAssertNil([self.thirdButton selectedButton]); + + // second and third button should be selected. + XCTAssertFalse([[self.firstButton selectedButtons] containsObject:self.firstButton]); + XCTAssertTrue([[self.firstButton selectedButtons] containsObject:self.secondButton]); + XCTAssertTrue([[self.firstButton selectedButtons] containsObject:self.thirdButton]); + + // first and second button should be selected. + [self.firstButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + [self.thirdButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + XCTAssertTrue([[self.secondButton selectedButtons] containsObject:self.firstButton]); + XCTAssertTrue([[self.secondButton selectedButtons] containsObject:self.secondButton]); + XCTAssertFalse([[self.secondButton selectedButtons] containsObject:self.thirdButton]); +} + @end