web-dev-qa-db-ja.com

SwiftからObjective-Cの可変メソッドをどのように呼び出しますか?

Objective-cに次のような静的メソッドを持つクラスがあるとします。

+ (NSError *)executeUpdateQuery:(NSString *)query, ...;

それをSwiftから呼び出すにはどうすればよいですか?オートコンプリートはそれを認識せず、コンパイラーは以下に不満があります。

MyClassName.executeUpdateQuery("")

「MyClassName.TypeにexecuteUpdateQueryという名前のメンバーがない」という不満

35
rustyshelf

Variadicメソッドのva_listバージョンを記述します。

+ (NSError *)executeUpdateQuery:(NSString *)query, ...
{
    va_list argp;
    va_start(argp, query);
    NSError *error = [MyClassName executeUpdateQuery: query args:argp];
    va_end(argp);

    return error;
}

+ (NSError *)executeUpdateQuery:(NSString *)query args:(va_list)args
{
    NSLogv(query,args);
    return nil;
}

これはSwiftから呼び出すことができます

MyClassName.executeUpdateQuery("query %d, %d %d", args: getVaList([1,2,3,4]))

ネイティブをサポートする拡張機能を追加Swift variadic args:

protocol CFormatFunction {
    class func executeUpdateQuery(format: String, _ args: CVarArg...) -> NSError?
}

extension MyClassName : CFormatFunction {
    class func executeUpdateQuery(format: String, _ args: CVarArg...) -> NSError?
    {
        return MyClassName.executeUpdateQuery(format, args:getVaList(args))
    }
}

MyClassName.executeUpdateQuery("query %d %@ %.2f", 99, "Hello", 3.145)

SwiftはNS_FORMAT_FUNCTION警告を提供しません(-Wformat)

MyClassName.executeUpdateQuery("query %@", 99)
48
Simon

CVArgTypeは、C "varargs" APIをSwiftでネイティブに表示するのに役立ちます。 ((Swift Docs)

あなたが持っている場合

+ (int)f1:(int)n, ...;

最初にva_listバージョンを作成する必要があります:

+ (int)f2:(int)n withArguments:(va_list)arguments

これは、可変コードバージョンからva_listバージョンを呼び出すことで コードを複製せずに で実行できます。独自の可変関数を記述しなかった場合、それができない可能性があります( この参照 で説明されています)。

このメソッドを取得したら、次のように記述できますSwiftラッパー:

func swiftF1(x: Int, _ arguments: CVarArgType...) -> Int {
     return withVaList(arguments) { YourClassName.f2(x, withArguments :$0) }
}

省略された外部パラメーター名(argumentsの前の_)は、swiftF1の呼び出し構文になります通常のC可変関数のように:

swiftF1(2, some, "other", arguments)

また、この例ではgetVaListを使用していません。これは、 docs が「最善の回避策である」と言っているためです。 」

必要に応じて、この関数を元のクラスのSwift拡張に追加することもできます。

6
divergio

目的C

MyClassName.h

+ (BOOL)executeSQL:(NSString *)sql args:(va_list)args;

MyClassName.m

+ (BOOL)executeSQL:(NSString *)sql args:(va_list)arguments
{
    NSLogv(sql, arguments);

    sql = [[NSString alloc] initWithFormat:sql arguments:arguments];
    va_end(arguments);
}

Swift-クラスに追加するWorks perfect

protocol CFormatFunction {
   class func executeSQLArg(format: String, _ args: CVarArgType...) -> Bool
}

extension MyClassName : CFormatFunction {
   class func executeSQLArg(format: String, _ args: CVarArgType...) -> Bool
   {
        return MyClassName(format, args:getVaList(args))
   }
 }

使い方

Swift

MyClassName.executeSQLArg(query, "one","two",3)

オブジェティブC

[MyClassName executeSQLArg:query, @"one",@"two",@3]
1
Bruno