在ObjectiveC中遇到...
的一些问题。
我基本上包装了一个方法,并希望接受一个nil
终止列表,并直接将相同的列表传递给我正在包装的方法。
这是我所拥有的,但它会导致EXC_BAD_ACCESS
崩溃。检查本地变量时,当otherButtonTitles
传递给NSString
时,otherButtonTitles:@"Foo", nil]
只是+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
[alert show];
}
时出现
nil
我如何简单地从传入参数传出到传出的参数,保留完全相同的{{1}}终止列表?
答案 0 :(得分:40)
你不能这样做,至少不是你想要的方式。你想做什么(传递变量参数)需要在UIAlertView
上有一个接受va_list
的初始值设定项。没有一个。但是,您可以使用addButtonWithTitle:
方法:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil] autorelease];
if (otherButtonTitles != nil) {
[alert addButtonWithTitle:otherButtonTitles];
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}
这当然是非常特定于问题的。真正的答案是“你不能隐式地将变量参数列表传递给没有va_list
参数的方法/函数”。因此,您必须找到解决问题的方法。在您给出的示例中,您希望使用传入的标题创建一个alertView。幸运的是,UIAlertView
类有一个方法可以迭代调用以添加按钮,从而实现相同的整体效果。如果它没有这种方法,那你就不走运了。
另一个非常混乱的选择是使它成为一个可变的宏。可变宏看起来像这样:
#define SHOW_ALERT(title,msg,del,cancel,other,...) { \
UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; \
[_alert show]; \
}
但是,即使使用可变参数宏方法,每次要执行此操作时仍需要自定义宏。这不是一个非常可靠的选择。
答案 1 :(得分:0)
如何构建 NSInvocation
对象?由于参数必须通过指针传递,因此您可以将指针传递给以nil结尾的列表。
您还可以使用marg_list()
迭代参数并自行构建一个未终止的列表。
这些只是简单的建议;我还没试过。
答案 2 :(得分:0)
这是针对OP的UIAlertView
- 包装案例,仅在iOS7上进行了测试:看起来UIAlertView
初始化otherButtons:nil
,然后设置其样式到UIAlertViewStylePlainTextInput
它不会调用其委托的alertViewShouldEnableFirstOtherButton:
来验证输入。我不确定这是一个错误或预期的行为,但它打破了我最不惊讶的原则。这可以通过以下方式重现(我假设委托的alertViewShouldEnableFirstOtherButton:
已经实现):
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Title"
message:@"message"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[av setAlertViewStyle:UIAlertViewStylePlainTextInput];
[av addButtonWithTitle:@"OK"];
[av show];
由于UIAlertView乐意接受otherButtons:nil
,因此解决方案是使用otherButtonTitles(可以是nil)初始化UIAlertView
,并迭代可变参数,如上所述:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
// add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here
if (otherButtonTitles != nil) {
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}