I have a simple class like this
.h
#interface DJMyClass : NSObject
+ (void)someFunction;
#end
.m
#import "DJJavaFunction+UIAlert.h"
#interface DJMyClass ()
#property (nonatomic, strong) NSString* someString;
#end
#implementation DJMyClass
+(void)functionWithName:(NSString *)functionName
callbackId:(int)callbackId
args:(NSArray *)args
{
DJMyClass *newFunction = [[DJMyClass alloc] init];
newFunction.function = functionName;
newFunction.callbackId = callbackId;
newFunction.args = args;
[newFunction processFunction];
}
- (void)processFunction
{
[self showAlertWithTitle:title message:message buttons:buttons inputField:inputField callbackId:_callbackId];
}
#end
Now I have created different extensions of this class, which I import and use within this class.
.h
#interface DJMyClass (UIAlert) <UIAlertViewDelegate>
- (void)showAlertWithTitle:(NSString *)title
message:(NSString *)message
buttons:(NSArray *)buttons
inputField:(NSDictionary *)inputField
callbackId:(int)callbackId;
#end
.m
#implementation DJJavaFunction (UIAlert)
- (void)showAlertWithTitle:(NSString *)title
message:(NSString *)message
buttons:(NSArray *)buttons
inputField:(NSDictionary *)inputField
callbackId:(int)callbackId
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
// Add the buttons
for (NSString *btn in buttons)
{
[alert addButtonWithTitle:btn];
}
// Add text field
if (!inputField)
{
alert.alertViewStyle = UIAlertViewStyleDefault;
}
else
{
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField *textField = [alert textFieldAtIndex:0];
textField.placeholder = inputField[#"placeholder"];
textField.text = inputField[#"text"];
}
alert.delegate = self;
alert.tag = 44;
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
This all works well, except that the UIAlertViewDelegate methods are never called.
Is it even possible to respond to UIAlertViewDelegate calls from within a category?
Thanks
Related
so I'm trying to get a variable containing the name of a PDF file I wish to open in a UIweb View to show up in a label. I first identify the global variable in a seperate class here:
header:
#import <Foundation/Foundation.h>
extern NSString *PDFNameString;
extern NSString *PDFActualName;
#interface GlobalVars : NSObject
{
}
#property (nonatomic, strong) NSString *PDFActualName;
#property (nonatomic, strong) NSString *PDFNameString;
#end
.m:
#import "GlobalVars.h"
NSString *PDFNameString;
NSString *PDFActualName; //the name of the PDF file
#implementation GlobalVars
{
}
#end
then I have the menu where I have an alert dialog featuring a text field so that the user can input the PDF name:
.h
#import <Foundation/Foundation.h>
#import "GlobalVars.h"
#interface TitleViewController : UIViewController{
NSFileManager *FM1;
}
#property (retain, nonatomic) IBOutlet UIBarButtonItem *OpenPDF;
#property (retain, nonatomic) IBOutlet UIBarButtonItem *ViewPDF;
-(void)OpeningPDF;
-(void)alertView;
#end
.m
#import "TitleViewController.h"
#interface TitleViewController ()
#end
#implementation TitleViewController
UIAlertView * alert;
UITextField *textField;
int StopTheAlerts = 0;
- (void)viewDidLoad
{
[super viewDidLoad];
FM1 = [NSFileManager defaultManager];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)ButtonClicked:(id)sender {
self.OpeningPDF;
}
- (void)dealloc {
[_OpenPDF release];
[_ViewPDF release];
[super dealloc];
}
- (void)OpeningPDF
{
StopTheAlerts = 0;
alert = [[UIAlertView alloc]
initWithTitle:#"Please enter a valid PDF name below:"
message:#"(Please add .PDF on the end!) \n \n"
delegate:self cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok", nil];
textField = [[UITextField alloc] init];
[textField setBackgroundColor:[UIColor whiteColor]];
textField.delegate = nil;
textField.borderStyle = UITextBorderStyleLine;
textField.frame = CGRectMake(15, 90, 255, 30);
textField.placeholder = #"PDF name";
textField.keyboardAppearance = UIKeyboardAppearanceAlert; //set up an alert box with a text field
[textField becomeFirstResponder];
[alert addSubview:textField];
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
PDFNameString = textField.text; //set the PDF name variable to the name entered
PDFActualName = textField.text;
NSArray *Paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocumentDir = [Paths objectAtIndex:0];
NSString *TempFilePath = PDFNameString;
PDFNameString = [DocumentDir stringByAppendingPathComponent:TempFilePath];
if([FM1 fileExistsAtPath: PDFNameString]){
_ViewPDF.enabled = true;
}
else {
while(StopTheAlerts <= 0){
UIAlertView *ErrorAlert = [[UIAlertView alloc]
initWithTitle:#"This file dosn't exist!"
message:#"Please reenter the file name!"
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[ErrorAlert show];
[ErrorAlert release];
StopTheAlerts = 1;
}
}
}
#end
This part all works fine, however, when I switch over the the view that contains the UIWebView to actually view the PDF (I've removed that in this part of the code) it has the old "message sent to deallocated instance 0xdb8fca0" error when I try to assign my global variable to the label containing the PDF name, this error also occurs when trying to get the UIWebView to read the PDF using the other global variable.
.h
#import <UIKit/UIKit.h>
#import "GlobalVars.h"
#interface ViewController : UIViewController
#property (retain, nonatomic) IBOutlet UILabel *PDFNameL;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_PDFNameL.text = PDFActualName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_PDFNameL release];
[super dealloc];
}
#end
If anyone knows a solution to the problem I would be very happy
thanks
I am tryin to pass the user login emial to other view controllers. It is going from a UITextField to a UILabel but it display null when I log in a user. I want it to display the email name in the UILabel field. Any help? here are my files.
vc1.h
#import <UIKit/UIKit.h>
#interface loginUserViewController : UIViewController
#property (nonatomic, strong) IBOutlet UITextField *email;
#property (nonatomic, retain) IBOutlet UITextField *password;
#property (nonatomic, retain) IBOutlet UIButton *login;
#property (nonatomic,retain) IBOutlet UIButton *registerBtn;
-(IBAction)loginUser:(id)sender;
#end
vc2.h
#import <UIKit/UIKit.h>
#import "loginUserViewController.h"
#interface Home : UIViewController
#property (weak, nonatomic) IBOutlet NSString *getEmail;
#property (weak, nonatomic) IBOutlet UILabel *username;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *Nav;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *logout;
-(IBAction)logout:(id)sender;
-(IBAction)bandHome:(id)sender;
#end
vc2.m
import "Home.h"
#import "loginUserViewController.h"
#interface Home ()
#end
#implementation Home
#synthesize getEmail,username, band1, band2, band3;
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self){
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
// loginUserViewController *object = [[loginUserViewController alloc]init];
// NSString *string = [[NSString alloc] initWithFormat:#"%#", object.email.text];
username.text = getEmail;
}
vc1.m
#import "loginUserViewController.h"
#import "Home.h"
#import "createBandViewController.h"
#interface loginUserViewController ()
#end
#implementation loginUserViewController
#synthesize email, password;
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)viewDidload
{
[super viewDidLoad];
}
-(IBAction)loginUser:(id)sender {
if ([email.text isEqualToString:#""] || [password.text isEqualToString:#""])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"alert" message:#"Please Fill all the field" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
NSMutableString *strURL = [[NSMutableString alloc] initWithFormat:#"Pretend reference/login2.php?email=%#&password=%#", email.text, password.text ];
[strURL setString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSMutableString *strResult = [[NSMutableString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSLog(#"logging in");
if ([strResult isEqualToString:#"1"])
{
NSLog(#"Logged in!");
[self performSegueWithIdentifier:#"login" sender:self];
Home *VC;
VC = [self.storyboard instantiateViewControllerWithIdentifier:#"Home"];
[self.navigationController pushViewController:VC animated:YES];
VC.getEmail = self.email.text;
}else
{
// invalid information
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"alert" message:#"Invalide Information" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return;
}
//email.text = #"";
password.text = #"";
}
-(void)WillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
// Dismisses keyboard by clicking out and hitting return key.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}
-(BOOL)textFieldShouldReturn:(UITextField *) textField {
[textField resignFirstResponder];
return YES;
}
#end
vc2.h
#property (weak, nonatomic) IBOutlet NSString *getEmail;
vc2.m
#synthesize getEmail;
-(void)viewDidLoad
{
[super viewDidLoad];
username.text = getEmail;
}
vc1.m
-(IBAction)loginUser:(id)sender {
if ([email.text isEqualToString:#""] || [password.text isEqualToString:#""])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"alert" message:#"Please Fill all the field" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
else
{
vc2 *VC;
VC = [self.storyboard instantiateViewControllerWithIdentifier:#"vc2Identifier"];
[self.navigationController pushViewController:VC animated:YES];
VC.getEmail = self.email.text
}
}
You don't need to alloc and init the view controller where you have to get the data , but you have to pass the data from vc1 to vc2 and use the variable of vc2 in vc1 , And what your were doing was using the vc1 value in vc2 . And you were allocating the LoginViewController , and in viewDidUnload method , you have set email textfield as nil . that is why you were getting nil value in vc2
I created one NSObject class in which I created some common functions. I created function which show UIAlertView. It works fine. But when I click on alert button, didDismissWithButtonIndex delegate method not called.
+ (void)showMessage:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:JMESSAGETITLE message:message delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert postHideAlertNotification:0];
[alert show];
}
#pragma mark - UIAlertView Delegate
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Hello");
}
I don't know what the problem is.
The self in this line
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:JMESSAGETITLE message:message delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
indicates the NSObject class not an object. You have to change the class method to instance method or create an object of NSObject class and set this object as delegate.
For object creation you can use singleton pattern.
+ (YourClass *)sharedInstance {
static dispatch_once_t once;
static YourClass *sharedMyClass;
dispatch_once(&once, ^ {
sharedMyClass = [[self alloc] init];
});
return sharedMyClass;
}
+ (void)showMessage:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: JMESSAGETITLE message:message delegate:[YourClass sharedInstance] cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
Try this:
Confirm to UIAlertViewDelegate protocol in the NSObject class like this:
#interface yourClass : NSObject <UIAlertViewDelegate>
Make UIAlertView *alert object as instance variable of the class or
property. Like this:
#interface yourClass : NSObject <UIAlertViewDelegate>
#property (nonatomic, strong) UIAlertView *alert;
#end
In the method where you are using the alert object, set the delegate self.alert.delegate = self
I have found this solution to making the next buttons on the ui keyboard go to the next text field, however it is not working at all for me. Is there something I have to do in the storyboard as well? Also, how do I make the next button for the final textfield call the unwind segue? Thank you
//
// AddToDoItemViewController.m
// ToDoList
//
// Copyright (c) 2015 com.example. All rights reserved.
//
#import "AddToDoItemViewController.h"
#interface AddToDoItemViewController ()
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#property (weak, nonatomic) IBOutlet UITextField *totalTextField;
#property (weak, nonatomic) IBOutlet UITextField *tipTextField;
#property (weak, nonatomic) IBOutlet UIView *singleTableView;
#property (weak, nonatomic) IBOutlet UISwitch *ccSwitch;
#end
#implementation AddToDoItemViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.textField) {
[self.totalTextField becomeFirstResponder];
}
else if (textField == self.totalTextField ) {
[self.tipTextField becomeFirstResponder];
}
else{
[textField resignFirstResponder];
}
return YES;
}
/*- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
} else if (theTextField == self.totalTextField) {
[self.tipTextField becomeFirstResponder];
}
return YES;
}
*/
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
NSLog(#"sender = %#",sender);
if (sender != self.saveButton) return YES;
NSNumberFormatter *formatter1 = [[NSNumberFormatter alloc] init];
NSNumber *totalOrder = [formatter1 numberFromString:self.totalTextField.text];
NSNumber *tipOrder = [formatter1 numberFromString:self.tipTextField.text];
double tot = totalOrder.doubleValue;
double totalOrderWithTip = tipOrder.doubleValue;
if(self.textField.text.length <= 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Field not entered"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
if(self.totalTextField.text.length <= 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Field not entered"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
if(self.tipTextField.text.length <= 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Field not entered"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
if(totalOrder == nil)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Invalid Order Total"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
if(tipOrder == nil)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Invalid Amount Recieved"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
if(totalOrderWithTip < tot)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"The amount recieved must be equal to or greater than the order total."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
return YES;
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (sender != self.saveButton) return;
if (self.textField.text.length > 0) {
NSNumberFormatter *formatter1 = [[NSNumberFormatter alloc] init];
// NSNumber *tipPercent = [[NSNumber alloc] initWithFloat:0.0];
NSNumber *totalOrder = [formatter1 numberFromString:self.totalTextField.text];
NSNumber *tipOrder = [formatter1 numberFromString:self.tipTextField.text];
NSNumber *actualTip = [[NSNumber alloc] initWithFloat:tipOrder.doubleValue - totalOrder.doubleValue];
double tot = totalOrder.doubleValue;
double tip1 = tipOrder.doubleValue - tot;
self.toDoItem = [[ToDoItem alloc] init];
self.toDoItem.location = self.textField.text;
NSNumber *percent1 = [[NSNumber alloc] initWithDouble:(tip1/tot)*100.0];
if(self.ccSwitch.isOn)
self.toDoItem.isCreditCard = YES;
else
self.toDoItem.isCreditCard = NO;
self.toDoItem.total = totalOrder;
self.toDoItem.tip = actualTip;
self.toDoItem.percentage = percent1;
self.toDoItem.completed = NO;
}
}
#end
In the Connections Inspector for the textField, drag from the "circle" under the section "Outlets" - "delegate", to the View Controller Icon. Or either you can set it in the viewDidLoad method. Some like:
self.textField.delegate = self;
The last textField is closing the keyboard because your are telling the keyboard to resign its first responder condition. Just replace that line for the one that you want to call:
[self shouldPerformSegueWithIdentifier:#"YOUR_IDENTIFIER" sender:your_sender];
And that's it!
I have developed this class that is basically a UIAlertView with an input field that runs on blocks. So, whatever the user does on the alertView (click cancel, ok, or fill the text), returns to a block:
HEADER
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
IMPLEMENTATION
#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
I run it, it shows the alertView with the message, placeholder, perfect. I click cancel or fill the text and press ok and the alertview:clickedButtonAtIndex: is never triggered. I am not seeing why.
thanks
You can directly subclass UIAlertView and add your own initializer. I have abstracted your classes to a single subclass of UIAlertView and it works fine. Please see my posts below,
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
Then, you could call it with the block in your view controller just like this,
- (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];
}
You haven't shown us how you're calling this but most likely your AlertViewBlocoComInput is a local variable that has fallen out of scope and is therefore deallocated before the user completes their input. You can demonstrate this by temporarily adding a dealloc method that will tell you when the object is deallocated.
- (void)dealloc {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
In terms of fixing this, you could make your AlertViewBlocoComInput instance a class property, so it won't be released until you manually nil it. Or you can make AlertViewBlocoComInput maintain a strong reference to itself until clickedButtonAtIndex is called.
Or, easiest, leverage the fact that UIAlertView already retains itself, so you can retire AlertComBloco altogether, folding it into 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
And you'd call it like so:
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];