如何在 UISegmentedControl 更改为新段之前实现回调?
How can I implement a callback before UISegmentedControl change to a new segment?
使用 UISegmentedControl
我想在 select 索引之前显示警告。问题是 UIControlEventValueChanged
的操作是在 selected 新段之后调用的。如何在 UISegmentedControl
更改段之前实现回调并决定它是否应该更改?
您可以通过获取 selectedSegmentIndex 值然后立即设置控件来对控件进行“trick”排序 selectedSegmentIndex 值为-1,所以选择基本上被推迟了。
一个包含两个段的基本示例类似于 -
- (IBAction)segmentedIndexDidChange:(UISegmentedControl*)sender {
// grab the segment index value and store
NSInteger indexToQuery = sender.selectedSegmentIndex;
// deselect any segments while making decisions
sender.selectedSegmentIndex = -1;
// now we have a willChange scenario instead of didChange
switch (indexToQuery) {
case 0: {
NSLog(@"seg index will change to 0");
//.. do stuff .. make decisions .. etc.
break;
}
case 1: {
NSLog(@"seg index will change to 1");
//.. do stuff
break;
}
default:
break;
}
}
// remember to config the segmented control after all is done
我已经为你实现了 UISegmentedControl
的子类来处理 willSelectIndex
和 shouldSelectIndex
的事件并使用委托模式:
ITDSegmentedControl.h
#import <UIKit/UIKit.h>
@class ITDSegmentedControl;
@protocol ITDSegmentedControlDelegate <NSObject>
@optional
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl willSelectIndex:(NSNumber *) index;
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl shouldSelectIndex:(NSNumber *) index andHandler:(void(^)(BOOL result))handler;
@end
@interface ITDSegmentedControl : UISegmentedControl
@property (nonatomic, weak) id<ITDSegmentedControlDelegate> delegate;
@end
ITDSegmentedControl.h
#import "ITDSegmentedControl.h"
@implementation ITDSegmentedControl
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGFloat x = [touch locationInView:self].x;
// Ignore touches that don't matter
if (x < 0 || x > self.frame.size.width) {
return;
}
NSUInteger index = (NSUInteger)floorf((CGFloat)x / (self.frame.size.width / (CGFloat)[self numberOfSegments]));
if ([self isEnabledForSegmentAtIndex:index]) {
if ([self.delegate respondsToSelector:@selector(segmentedControl:shouldSelectIndex:andHandler:)]) {
[self.delegate segmentedControl:self shouldSelectIndex:[NSNumber numberWithInteger:index] andHandler:^(BOOL result) {
if (result) {
if ([self.delegate respondsToSelector:@selector(segmentedControl:willSelectIndex:)]) {
[self.delegate performSelector:@selector(segmentedControl:willSelectIndex:) withObject:self withObject:[NSNumber numberWithInteger:index]];
self.selectedSegmentIndex = (NSInteger)index;
}
}
}];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!self.momentary) {
return;
}
self.selectedSegmentIndex = UISegmentedControlNoSegment;
[self setNeedsDisplay];
}
- (void)setSelectedSegmentIndex:(NSInteger)index {
[super setSelectedSegmentIndex:index];
}
@end
ViewController.h
#import "ITDSegmentedControl.h"
@interface ViewController: UIViewController <ITDSegmentedControlDelegate>
@property (weak, nonatomic) IBOutlet ITDSegmentedControl *mySegmented;
@end
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.mySegmented.delegate = self;
}
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl willSelectIndex:(NSNumber *) index
{
NSLog(@"willSelectIndex %zd",[index integerValue]);
}
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl shouldSelectIndex:(NSNumber *) index andHandler:(void(^)(BOOL result))handler
{
NSLog(@"shouldSelectIndex %zd",[index integerValue]);
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Alert"
message:@"Are you Sure"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel action")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
handler(NO);
NSLog(@"Cancel action");
}];
UIAlertAction *okAction = [UIAlertAction
actionWithTitle:NSLocalizedString(@"OK", @"OK action")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
handler(YES);
NSLog(@"OK action");
}];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
使用 UISegmentedControl
我想在 select 索引之前显示警告。问题是 UIControlEventValueChanged
的操作是在 selected 新段之后调用的。如何在 UISegmentedControl
更改段之前实现回调并决定它是否应该更改?
您可以通过获取 selectedSegmentIndex 值然后立即设置控件来对控件进行“trick”排序 selectedSegmentIndex 值为-1,所以选择基本上被推迟了。
一个包含两个段的基本示例类似于 -
- (IBAction)segmentedIndexDidChange:(UISegmentedControl*)sender {
// grab the segment index value and store
NSInteger indexToQuery = sender.selectedSegmentIndex;
// deselect any segments while making decisions
sender.selectedSegmentIndex = -1;
// now we have a willChange scenario instead of didChange
switch (indexToQuery) {
case 0: {
NSLog(@"seg index will change to 0");
//.. do stuff .. make decisions .. etc.
break;
}
case 1: {
NSLog(@"seg index will change to 1");
//.. do stuff
break;
}
default:
break;
}
}
// remember to config the segmented control after all is done
我已经为你实现了 UISegmentedControl
的子类来处理 willSelectIndex
和 shouldSelectIndex
的事件并使用委托模式:
ITDSegmentedControl.h
#import <UIKit/UIKit.h>
@class ITDSegmentedControl;
@protocol ITDSegmentedControlDelegate <NSObject>
@optional
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl willSelectIndex:(NSNumber *) index;
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl shouldSelectIndex:(NSNumber *) index andHandler:(void(^)(BOOL result))handler;
@end
@interface ITDSegmentedControl : UISegmentedControl
@property (nonatomic, weak) id<ITDSegmentedControlDelegate> delegate;
@end
ITDSegmentedControl.h
#import "ITDSegmentedControl.h"
@implementation ITDSegmentedControl
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGFloat x = [touch locationInView:self].x;
// Ignore touches that don't matter
if (x < 0 || x > self.frame.size.width) {
return;
}
NSUInteger index = (NSUInteger)floorf((CGFloat)x / (self.frame.size.width / (CGFloat)[self numberOfSegments]));
if ([self isEnabledForSegmentAtIndex:index]) {
if ([self.delegate respondsToSelector:@selector(segmentedControl:shouldSelectIndex:andHandler:)]) {
[self.delegate segmentedControl:self shouldSelectIndex:[NSNumber numberWithInteger:index] andHandler:^(BOOL result) {
if (result) {
if ([self.delegate respondsToSelector:@selector(segmentedControl:willSelectIndex:)]) {
[self.delegate performSelector:@selector(segmentedControl:willSelectIndex:) withObject:self withObject:[NSNumber numberWithInteger:index]];
self.selectedSegmentIndex = (NSInteger)index;
}
}
}];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!self.momentary) {
return;
}
self.selectedSegmentIndex = UISegmentedControlNoSegment;
[self setNeedsDisplay];
}
- (void)setSelectedSegmentIndex:(NSInteger)index {
[super setSelectedSegmentIndex:index];
}
@end
ViewController.h
#import "ITDSegmentedControl.h"
@interface ViewController: UIViewController <ITDSegmentedControlDelegate>
@property (weak, nonatomic) IBOutlet ITDSegmentedControl *mySegmented;
@end
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.mySegmented.delegate = self;
}
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl willSelectIndex:(NSNumber *) index
{
NSLog(@"willSelectIndex %zd",[index integerValue]);
}
-(void) segmentedControl:(ITDSegmentedControl *)segmentedControl shouldSelectIndex:(NSNumber *) index andHandler:(void(^)(BOOL result))handler
{
NSLog(@"shouldSelectIndex %zd",[index integerValue]);
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Alert"
message:@"Are you Sure"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel action")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
handler(NO);
NSLog(@"Cancel action");
}];
UIAlertAction *okAction = [UIAlertAction
actionWithTitle:NSLocalizedString(@"OK", @"OK action")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
handler(YES);
NSLog(@"OK action");
}];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}