0

I have a singleton WarningManager class in my project looks as follows

WarningManager.h file

+ (WarningManager *)getInstance;

- (void) createAndPushWarning:(id<UIAlertViewDelegate>)actionDelegate isLocalisedStrings:(BOOL)localized text:(NSString *)text cancel:(NSString *)cancel buttons:(NSString*)firstObj, ...  NS_REQUIRES_NIL_TERMINATION;

WarningManager.m file

static WarningManager *instance = nil;

+ (WarningManager *) getInstance {
    if (!instance) {
        instance = [[self alloc] init];
    }
    return instance;
}

    - (void) createAndPushWarning:(id<UIAlertViewDelegate>)actionDelegate isLocalisedStrings:(BOOL)localized text:(NSString *)text cancel:(NSString *)cancel buttons:(NSString*)firstObj, ... {
        va_list argumentList;
        va_start(argumentList, firstObj);

        NSMutableArray *buttonArray = [NSMutableArray array];

        if(firstObj){
            if(!localized){
                [buttonArray addObject:NSLocalizedString(firstObj, @"")];
            } else {
                [buttonArray addObject:firstObj];
            }
            id eachObject;
            while ((eachObject = va_arg(argumentList, id))){
                if(!localized){
                    [buttonArray addObject: NSLocalizedString(eachObject, @"")];
                }else{
                    [buttonArray addObject: eachObject];
                }
            }
        }

        if (!localized) {
            if(text){
                text = NSLocalizedString(text, @"");
            }
            if(cancel){
                cancel = NSLocalizedString(cancel, @"");
            }
        }

        va_end(argumentList);

        LogW(@"Warning : %@",text);

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"My App Name", @"") message:text delegate:actionDelegate cancelButtonTitle:cancel otherButtonTitles:nil];
        for (NSString *button in buttonArray) {
            [alertView addButtonWithTitle:button];
        }
        [alertView show];
    }

the above code works well when an objective - C class file calls as follows

[[WarningManager getInstance] createAndPushWarning:self isLocalisedStrings:NO text:@"Text want to display" cancel:nil buttons:@"Button 1", @"Button 2", nil];

Now I am creating swift classes and I want to use this same warning manager in it but variadic function syntax changed in swift so I have added another method by replacing variadic arguments as follows in WarningManager class.

WarningManager.h file

- (void) createAndPushWarning:(id<UIAlertViewDelegate>)actionDelegate isLocalisedStrings:(BOOL)localized text:(NSString *)text cancel:(NSString *)cancel agruments:(va_list)buttons

WarningManager.M file

- (void) createAndPushWarning:(id<UIAlertViewDelegate>)actionDelegate isLocalisedStrings:(BOOL)localized text:(NSString *)text cancel:(NSString *)cancel agruments:(va_list)buttons {

    [self createAndPushWarning:actionDelegate isLocalisedStrings:localized text:text cancel:cancel buttons:(__bridge NSString *)(buttons), nil];
}

To call this from a swift class I have created an extension to WarningManager class as follows in WarningManager+ArgumentList.swift file

extension WarningManager {

    class func WarningWrapper(actionDelegate: UIAlertViewDelegate, isLocalizedString: Bool, text:String, cancel: String, _ args: CVarArg...) {

        withVaList(args) { _ in WarningManager.getInstance().createAndPushWarning(actionDelegate, isLocalisedStrings: isLocalizedString, text: text, cancel: cancel, agruments: getVaList(args)) }
    }
}

Calling my extension method from swift class

 WarningManager.WarningWrapper(actionDelegate: self, isLocalizedString: false, text: "Message to Display", cancel: "OK", "")

So when I call this extension from my swift class I am getting bad access error

enter image description here

but I change my WarningManager.m file like this it displays the alert.

- (void) createAndPushWarning:(id<UIAlertViewDelegate>)actionDelegate isLocalisedStrings:(BOOL)localized text:(NSString *)text cancel:(NSString *)cancel agruments:(va_list)buttons {

    [self createAndPushWarning:actionDelegate isLocalisedStrings:localized text:text cancel:cancel buttons:nil];
}

Somewhere I am making mistake in sending the arguments I am not sure how to fix this.

any suggestions and ideas are appreciated, Thanks In Advance for people who read this question this far.

Peer Mohamed Thabib
  • 636
  • 2
  • 9
  • 29

1 Answers1

1

You can't pass a va_list where an actual list of arguments is required, even if they are variadic. Think of a va_list as an array. You can't pass an array where a parameter list is required and expect each array item to be treated as an individual parameter. The entire array is passed as a single first parameter.

In an ideal world you would get an error about this (and in pure Swift you would), but C's variadic parameter lists do not include enough type information to be able to detect this error.

You need to reverse your code: put most of the code into the va_list-taking version (with the "arguments:" parameter) and then call that from the variadic version, which simply calls va_start, calls the va_list version, and then calls va_end.

uliwitness
  • 8,532
  • 36
  • 58