Вызов инициализатора Objective-C с переменными аргументами

Я пытаюсь повторно использовать класс Objective-C, а именно TSAlertView , в проект Swift. Проблема в том, что класс использует инициализатор с переменными аргументами. Я придерживался того же подхода, предложенного в этом вопросе stackoverflow, и мой код работает в iOS Simulator, если я использую iPad Air, но НЕ, если я использую iPad Retina. Код также падает на реальном iPad 3.

Я смог создать игрушечный пример, который показывает ту же проблему.

TestClass.h

#import <Foundation/Foundation.h> @interface TestClass : NSObject @property NSArray *titles; - (id)initWithTitle:(NSString *)title otherButtonTitlesVA:(va_list)args; @end 

TestClass.m

 #import "TestClass.h" @implementation TestClass - (id)initWithTitle:(NSString *)title otherButtonTitlesVA:(va_list)args { NSMutableArray *titles = [NSMutableArray array]; if ((self = [super init])) { [titles addObject:title]; id arg; if ((arg = va_arg(args, id)) && [arg isKindOfClass:[NSString class]]) { // this causes an EXC_BAD_ACCESS on iPad Retina [titles addObject:(NSString*)arg]; while ( nil != ( arg = va_arg( args, id ) ) ) { if ( ![arg isKindOfClass: [NSString class] ] ) return nil; [titles addObject:(NSString*)arg]; } } } self.titles = [NSArray arrayWithArray:titles]; return self; } @end 

TestClass + Swift.swift

 import Foundation extension TestClass { convenience init(title:String?, otherButtonTitles:CVarArgType...) { self.init(title: title, otherButtonTitlesVA:getVaList(otherButtonTitles)) } } 

ViewController.swift

 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let testObject1 = TestClass(title: "First", otherButtonTitles: "Second", "Third") let testObject2 = TestClass(title: "First") // this causes the initializer to crash on iPad Retina NSLog("%@", testObject1.titles) NSLog("%@", testObject2.titles) } } 

При попытке создать testObject2 с EXC_BAD_ACCESS . Что-то не так с моим кодом? Почему iPad Air отличается от iPad Retina поведением?

EDIT: Хорошо, я думаю, проблема заключается в том, что код Objective-C ожидает nil списка. Как передать nil оканчивающийся va_list из Swift?

    Как вы уже выяснили, код Objective-C ожидает nil списка. Без этого поведение

     if ((arg = va_arg(args, id)) && [arg isKindOfClass:[NSString class]]) { ... } 

    не определено, если список фактически прошедших аргументов исчерпан.

    nil – это указатель NULL в Objective-C, и вы можете добавить, что в вашем удобстве инициализатор:

     extension TestClass { convenience init(title:String?, otherButtonTitles : CVarArgType...) { let nullPtr = UnsafePointer<Void>() let otherTitles : [CVarArgType] = otherButtonTitles + [nullPtr] self.init(title: title, otherButtonTitlesVA: getVaList(otherTitles)) } } 

    Кажется, что это правильно работает на 32- и 64-разрядных платформах.


    Обновление для Swift 3:

     extension TestClass { convenience init(title:String?, otherButtonTitles : CVarArg...) { let otherTitles : [CVarArg] = otherButtonTitles + [Int(0)] self.init(title: title, otherButtonTitlesVA: getVaList(otherTitles)) } } 

    Как упоминалось в https://bugs.swift.org/browse/SR-5046 , использование нулевого размера по умолчанию является рекомендуемым способом передачи нулевого указателя в списке переменных аргументов.

    Interesting Posts

    Хранение короткого аудиофайла / Потоковая передача в приложении

    Возможно ли динамическое расширение иерархии NSProgress после того, как начался прогресс?

    Индикатор выбора UIPickerView не отображается в iOS10

    Предотвращение MFMailComposeViewController от масштабирования анимированных GIF-файлов

    Недопустимые значки пути к изображениям ios7 при развертывании в appstore через Application Loader

    Как определить жест flick с использованием UISwipeGestureRecognizer?

    Как заполнить путь безье с градиентным цветом

    Покупка этого товара в настоящее время недоступна

    iOS Processes Info (pid, uid, cpu, mem, …)

    Передать элемент массива ячеек в другой контроллер представления

    как перезагружать / перезапускать анимацию и постоянно ли она отображаться?

    Как получить код языка разницы для iOS 7 AVSpeechUtterance текст в речь?

    Как получить (X, Y) координату касания в UIWebView

    Как я могу перемещать CGRect с помощью UITouches?

    Механизм KVO между двумя UIViewControllers в UITABViewController

    Давайте будем гением компьютера.