如何在 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 的子类来处理 willSelectIndexshouldSelectIndex 的事件并使用委托模式:

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];


}