Вопрос по iphone, objective-c – Блок для UIAlertViewDelegate
Я довольно плохо знаком с задачей C и просто пытаюсь выяснить, могу ли я использовать блок или селектор в качестве аргумента UIAlertViewDelegate для UIAlertView - и какой из них более уместен?
Я пробовал следующее, но оно просто не работает, поэтому я не уверен, нахожусь ли я на правильном пути или нет?
<code> UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Checked In" message:responseString delegate:^(UIAlertView * alertView, NSInteger buttonIndex) { NSLog(@"Done!"); } cancelButtonTitle:@"OK" otherButtonTitles: nil]; </code>
Спасибо!
чтобы остановить ошибку компилятора. Просто небольшой твик и xcode был счастлив.
UIAlertViewBlock *alert = [[UIAlertViewBlock alloc] initWithTitle:@"hi"
message:@"hi there"
completion:^(BOOL canceled,NSInteger buttonIndex) {
NSLog(@"canceled=%d", canceled);
NSLog(@"pressed=%d", buttonIndex);
}
cancelButtonTitle:@"cancel"
otherButtonTitles:@"ok", nil];
[alert show];
как говорится в документе Apple
A UIAlertController объект отображает предупреждающее сообщение для пользователя. Этот класс заменяет классы UIActionSheet и UIAlertView для отображения предупреждений. После настройки контроллера предупреждений с необходимыми действиями и стилем представьте его, используя presentViewController: animated: завершение: метод.
Помимо отображения сообщения пользователю, вы можете связать действия с вашим контроллером оповещений, чтобы дать пользователю возможность ответить. Для каждого действия, добавляемого с помощью метода addAction:, контроллер предупреждений настраивает кнопку с подробностями действия. Когда пользователь касается этого действия, контроллер предупреждений выполняет блок, который вы указали при создании объекта действия. Apple Docs.
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"
message:@"This is an alert."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
как представление предупреждений, за исключением того, что добавляет свойство блока, которое вызывается при отклонении предупреждения. (Изменить - я упростил этот код с момента первоначального ответа. Вот что я сейчас использую в проектах)
// AlertView.h
//
#import <UIKit/UIKit.h>
@interface AlertView : UIAlertView
@property (copy, nonatomic) void (^completion)(BOOL, NSInteger);
- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles;
@end
//
// AlertView.m
#import "AlertView.h"
@interface AlertView () <UIAlertViewDelegate>
@end
@implementation AlertView
- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles {
self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
if (self) {
for (NSString *buttonTitle in otherButtonTitles) {
[self addButtonWithTitle:buttonTitle];
}
}
return self;
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (self.completion) {
self.completion(buttonIndex==self.cancelButtonIndex, buttonIndex);
self.completion = nil;
}
}
@end
Вы можете расширить эту идею, чтобы предоставлять блоки для других методов делегатов, но didDismiss является наиболее распространенным.
Звони так:
AlertView *alert = [[AlertView alloc] initWithTitle:@"Really Delete" message:@"Do you really want to delete everything?" cancelButtonTitle:@"Nevermind" otherButtonTitles:@[@"Yes"]];
alert.completion = ^(BOOL cancelled, NSInteger buttonIndex) {
if (!cancelled) {
[self deleteEverything];
}
};
[alert show];
:-)
см. мой ответ ниже.
Besi
cancelButtonTitle
параметр. Также было бы полезно иметь само оповещение в качестве аргумента блока (как в методе делегата), чтобы индекс кнопки можно было сравнить сalert.cancelButtonIndex
.
omz
используя шаблон категории, без подкласса, вызовите непосредственно UIAlertView. Пожалуйста, следуйте этим шагам:
Категория UIAlertView в .h файле
@interface UIAlertView (AlertWithBlock)
- (void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
- (void)setDelegateBlock:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
+ (id)alertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles delegate:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegate;
@end
В .m файле
@implementation UIAlertView(AlertWithBlock)
static char const *delegateBlockTagKey = "delegateBlockTagKey";
- (void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock
{
return objc_getAssociatedObject(self, delegateBlockTagKey);
}
- (void)setDelegateBlock:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock
{
objc_setAssociatedObject(self, delegateBlockTagKey, delegateBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (id)alertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles delegate:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegate
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
alert.delegate = alert;
alert.delegateBlock = [delegate copy];
for (NSString *buttonTitle in otherButtonTitles)
{
[alert addButtonWithTitle:buttonTitle];
}
[alert show];
return alert;
}
#pragma mark - Delegate
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.delegateBlock)
{
alertView.delegateBlock(alertView, buttonIndex);
}
}
@end
Звоните, как это
[UIAlertView alertWithTitle:@"Title" message:@"This is a message" cancelButtonTitle:@"Cancel" otherButtonTitles:@[@"Yes",@"No"] delegate:^(UIAlertView *alertView, NSInteger buttonIndex) {
NSLog(@"Click at button index %ld", buttonIndex);
}];
Надеюсь, это поможет.
которое является неполным, поскольку невозможно добавить несколько кнопок. Передача va_list в функцию немного сложнее: -)
Так что вы можете сделать это, чтобы иметь возможность добавить несколько кнопок кUIAlertView
:
- (id)initWithTitle:(NSString *)title message:(NSString *)message completion:(void (^)(NSInteger buttonIndex))completion cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... {
self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil ];
if(self){
_completion = completion;
va_list _arguments;
va_start(_arguments, otherButtonTitles);
for (NSString *key = otherButtonTitles; key != nil; key = (__bridge NSString *)va_arg(_arguments, void *)) {
[self addButtonWithTitle:key];
}
va_end(_arguments);
}
return self;
}
Обновит: Может быть лучший способ передачи va_list вsuper
. Я хотел бы упомянуть это для меняva_list
@ есть что-то мистическое для них: -)
надеюсь, оно будет полезным
import UIKit
extension UIAlertView {
func show(completion: (alertView: UIAlertView, buttonIndex: Int) -> Void){
self.delegate = AlertViewDelegate(completion: completion)
self.show()
}
class func showInput(title: String?, message: String?, cancellable: Bool, completion: (text: String?) -> Void){
var strOK = NSLocalizedString("OK",comment: "OK")
var strCancel = NSLocalizedString("Cancel",comment: "Cancel")
var alert = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: cancellable ? strCancel : strOK)
alert.alertViewStyle = UIAlertViewStyle.PlainTextInput
if(cancellable) {
alert.addButtonWithTitle(strOK)
}
alert.show { (alertView, buttonIndex) -> Void in
if(cancellable && alertView.cancelButtonIndex == buttonIndex) {
completion(text: nil)
return
}
completion(text: alertView.textFieldAtIndex(0)?.text)
}
}
private class AlertViewDelegate : NSObject, UIAlertViewDelegate {
var completion : (alertView: UIAlertView, buttonIndex: Int) -> Void
var retainedSelf : NSObject?
init(completion: (UIAlertView, Int) -> Void ) {
self.completion = completion
super.init()
self.retainedSelf = self
}
func alertView(alertView: UIAlertView, didDismissWithButtonIndex buttonIndex: Int) {
var retain = self
retain.retainedSelf = nil
retain.completion(alertView: alertView, buttonIndex: buttonIndex)
}
}
}
Категория UIAlertView-Blocks на Github. Я написал это и очень прост в использовании и хорошо работает.
Удачи