为什么这个代表没有触发是一个谜

时间:2014-10-12 17:47:14

标签: ios delegates uialertview

我开发了这个类,它基本上是一个带有在块上运行的输入字段的UIAlertView。因此,无论用户在alertView上做什么(单击取消,确定或填充文本),都会返回到块:

标题

typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);


@interface AlertViewBlocoComInput : NSObject

- (void)mostrarAlertViewBlocoComTitulo:(NSString *)titulo
                              mensagem:(NSString *)mensagem
                     tituloBotaoCancel:(NSString *)tituloCancel
                     outrosBotoesArray:(NSArray *)titulosOutrosBotoes
                   inputComPlaceHolder:(NSString *)textoPlaceholder
                      comBlocoExecucao:(onClickBlock)bloco;

@end

实施

@interface AlertComBloco : UIAlertView
@property (nonatomic, copy) onClickBlock runOnClickBlock;
@end


@implementation AlertComBloco
@end


@interface AlertViewBlocoComInput () <UIAlertViewDelegate>
@end


@implementation AlertViewBlocoComInput 


- (void)mostrarAlertViewBlocoComTitulo:(NSString *)titulo
                              mensagem:(NSString *)mensagem
                     tituloBotaoCancel:(NSString *)tituloCancel
                     outrosBotoesArray:(NSArray *)titulosOutrosBotoes
                   inputComPlaceHolder:(NSString *)textoPlaceholder
                      comBlocoExecucao:(onClickBlock)bloco

{

  AlertComBloco *alerta = [[AlertComBloco alloc] initWithTitle:titulo
                                                       message:mensagem
                                                      delegate:self
                                             cancelButtonTitle:tituloCancel
                                             otherButtonTitles:nil];
  alerta.runOnClickBlock =bloco;

  // adicionar os outros botões
  for (NSString *umOutroBotao in titulosOutrosBotoes) {
    [alerta addButtonWithTitle:umOutroBotao];
  }


  [alerta setAlertViewStyle:UIAlertViewStylePlainTextInput];
  UITextField *input = [alerta textFieldAtIndex:0];
  input.placeholder = textoPlaceholder;

  [alerta show];

}



- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

  AlertComBloco *alerta = (AlertComBloco *)alertView;
  onClickBlock bloco = alerta.runOnClickBlock;

  UITextField *input = [alertView textFieldAtIndex:0];

  if (bloco) {
    bloco(buttonIndex, input.text);
  }

}


@end

我运行它,它显示带有消息的alertView,占位符,完美。我单击取消或填写文本并按确定,从不触发alertview:clickedButtonAtIndex:。我不明白为什么。

感谢

2 个答案:

答案 0 :(得分:2)

您可以直接将UIAlertView子类化并添加自己的初始化程序。我已将您的类抽象为UIAlertView的单个子类,它工作正常。请参阅下面的帖子,

typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);

@interface AlertComBloco : UIAlertView<UIAlertViewDelegate>
@property (nonatomic, copy) onClickBlock runOnClickBlock;
@end


@implementation AlertComBloco


- (id)initWithTitulo:(NSString *)titulo mensagem:(NSString*)mensagem tituloBotaoCancel:(NSString*)tituloCancel outrosBotoesArray:(NSArray *)titulosOutrosBotoes inputComPlaceHolder:(NSString *)textoPlaceholder
    comBlocoExecucao:(onClickBlock)bloco{
  if(self = [self initWithTitle:titulo message:mensagem delegate:self cancelButtonTitle:tituloCancel otherButtonTitles:nil, nil]){
    _runOnClickBlock = bloco;
    for (NSString *umOutroBotao in titulosOutrosBotoes) {
      [self addButtonWithTitle:umOutroBotao];
    }
    [self setAlertViewStyle:UIAlertViewStylePlainTextInput];
    UITextField *input = [self textFieldAtIndex:0];
    input.placeholder = textoPlaceholder;

  }
  return self;
}



- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

  UITextField *input = [alertView textFieldAtIndex:0];

  if (self.runOnClickBlock) {
    self.runOnClickBlock(buttonIndex, input.text);
  }

}

@end

然后,您可以使用视图控制器中的块来调用它,就像这样,

- (void)showAlert:(id)sender{
  AlertComBloco *alertCombo = [[AlertComBloco alloc] initWithTitulo:@"Hi" mensagem:@"Custom Alert" tituloBotaoCancel:@"Cancel" outrosBotoesArray:@[@"Other"] inputComPlaceHolder:@"Placeholder" comBlocoExecucao:^(NSInteger buttonIndex, NSString *textoInput) {
    NSLog(@"Button at index %ld, with text %@", (long)buttonIndex, textoInput);
  }];
  [alertCombo show];
}

答案 1 :(得分:1)

您没有向我们展示您是如何调用它的,但很可能您的AlertViewBlocoComInput是一个超出范围的局部变量,因此在用户完成输入之前被释放。您可以通过临时添加dealloc方法来证明这一点,该方法将告诉您何时取消分配对象。

- (void)dealloc {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

在修复此问题方面,您可以将AlertViewBlocoComInput实例设为类属性,因此在手动nil之前不会释放它。或者,您可以AlertViewBlocoComInput在调用clickedButtonAtIndex之前保持对自身的强引用。

或者,最简单,利用UIAlertView已经保留的事实,因此您可以完全退出AlertComBloco,将其折叠为AlertViewBlocoComInput

typedef void (^onClickBlock)(NSInteger buttonIndex, NSString *textoInput);

@interface AlertViewBlocoComInput : UIAlertView <UIAlertViewDelegate>

- (instancetype)initComTitulo:(NSString *)titulo
                     mensagem:(NSString *)mensagem
            tituloBotaoCancel:(NSString *)tituloCancel
            outrosBotoesArray:(NSArray *)titulosOutrosBotoes
          inputComPlaceHolder:(NSString *)textoPlaceholder
             comBlocoExecucao:(onClickBlock)bloco;

@property (nonatomic, copy) onClickBlock runOnClickBlock;

@end

@implementation AlertViewBlocoComInput

- (instancetype)initComTitulo:(NSString *)titulo
                     mensagem:(NSString *)mensagem
            tituloBotaoCancel:(NSString *)tituloCancel
            outrosBotoesArray:(NSArray *)titulosOutrosBotoes
          inputComPlaceHolder:(NSString *)textoPlaceholder
             comBlocoExecucao:(onClickBlock)bloco

{
    self = [super initWithTitle:titulo message:mensagem delegate:self cancelButtonTitle:tituloCancel otherButtonTitles:nil];

    if (self) {
        self.runOnClickBlock =bloco;

        // adicionar os outros botões
        for (NSString *umOutroBotao in titulosOutrosBotoes) {
            [self addButtonWithTitle:umOutroBotao];
        }

        [self setAlertViewStyle:UIAlertViewStylePlainTextInput];
        UITextField *input = [self textFieldAtIndex:0];
        input.placeholder = textoPlaceholder;
    }

    return self;
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (self.runOnClickBlock) {
        UITextField *input = [alertView textFieldAtIndex:0];
        self.runOnClickBlock(buttonIndex, input.text);
    }
}

@end

你会这样称呼它:

AlertViewBlocoComInput *obj = [[AlertViewBlocoComInput alloc] initComTitulo:@"title" mensagem:@"message" tituloBotaoCancel:@"OK" outrosBotoesArray:nil inputComPlaceHolder:@"Placeholder" comBlocoExecucao:^(NSInteger buttonIndex, NSString *textoInput) {
    // do whatever you want with `buttonIndex` and `textoInput` here
    //
    // NSLog(@"%ld %@", (long)buttonIndex, textoInput);
}];
[obj show];
相关问题