2017-09-01 8 views
1

は、私の質問は:あなたがコンパイルx86_64版を使用する理由場合にのみ、このコンパイルエラーが発生しますか?そして、どのように解決するには?
私の質問は:選択x86_64版シミュレータ、コンパイルエラーが発生する理由場合にのみなぜ選択x86_64版シミュレータ「はブロック内の配列型で宣言を参照できない」だけComplieエラー

環境解決する方法:??のXcode v8.3.2
テストコード:コンパイルする

+ (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ... 
{ 
    va_list args; 
    va_start(args, key); 

    __block BOOL isOK = NO; 
    [_queue inDatabase:^(FMDatabase *_dataBase)// 
    { 
     isOK = [_dataBase executeUpdate:sql withVAList:args]; 
    }]; 

    va_end(args); 
    return isOK; 
} 
異なる方法、コンパイル時にエラーが場合
  • ]√[コンパイラ通常汎用IOSデバイスコンパイラ(ビルド):: [たARMv7 + arm64}

    0を選択
  • CompileC Test.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler 
    CompileC Test.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler 
    
  • ] [√通常のコンパイラ選択実機:iPhone 4(7.1.2)コンパイル(ビルド):[

    ]のARMv7
    CompileC Test.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler 
    
  • ]×[エラー選択シミュレータをコンパイル:iPhoneの5S (10.3)、iPhone SE(10.3)、iPhone 7プラス(10.3)コンパイラ(ビルド):[x86_64版]

    CompileC Test.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler 
    

    Complieエラー
    は、ブロック内の配列型と宣言を参照できません

  • [コンパイル正常√]シミュレータを選択:iPhone 5(10.3)コンパイル(ビルド):[I386]を

    CompileC Test.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler 
    

答えて

2

ブロックが非__block変数を捕捉する場合、変数のコピーは、ブロックは、ブロック内で作成されて記憶されるときにアレイがCに割り当てることができない。作られ、それはなぜのデザイナーであってもよいです。ブロックC規格で規定されていないされているタイプva_listのどんな;.それは配列型、ポインタ型、構造体として実装することができ、実装固有で

ブロック内の配列型の撮像変数を禁止タイプ、または何、これは同一のコンパイラ上アーキテクチャ間で異なることができるが。おそらく彼らはx86_64の中に配列型として実装され、他の3つの円弧上のいくつかの非配列型としてhitectures。このことについて珍しい何もありません。あなたは、あるタイプva_listの種類についての仮定を行うことができません。va_listがある場合に動作するように起こる、あなたが別の関数を定義し、それにva_listを渡すあなたの答えでは、

を配列型、Cは自動的に「Tへのポインタ」のタイプのいずれかのパラメータが「Tの配列」を調整するので、va_listが配列型(argsとは異なるタイプである場合メソッド+foo:key:withVAList:におけるパラメータargsは、実際にはポインタ型を有するため+foo:key:法)、およびポインタ変数は、ブロック微細に取り込むことができます。

va_listのアドレスを取得し、va_list *を取得し、それをブロックで使用される変数に入れることです。これは、va_listが何であるにせよ、ポインタ型であることが保証されており、ブロック単位で捕捉できます。ブロック内に実際にva_listを使用する必要がある場合は、ポインタを逆参照できます。たとえば、次のようなものがあります。

+ (BOOL)updateSqlByFileName:(NSString *)file key:(NSString *)key, ... 
{ 
    va_list args; 
    va_start(args, key); 
    va_list *ptrToArgs = &args; 

    __block BOOL isOK = NO; 
    [_queue inDatabase:^(FMDatabase *_dataBase) 
    { 
     isOK = [_dataBase executeUpdate:sql withVAList:*ptrToArgs]; 
    }]; 

    va_end(args); 
    return isOK; 
} 
-2
[効果]ソリューション(コード)を試した後:
+ (BOOL)foo:(NSString *)file key:(NSString *)key, ... 
{ 
    va_list args; 
    va_start(args, key); 

    BOOL isOK = [self foo:file key:key withVAList:args]; 

    va_end(args); 
    return isOK; 
} 

+ (BOOL)foo:(NSString *)file key:(NSString *)key withVAList:(va_list)args 
{ 
    __block BOOL isOK = NO; 
    [_queue inDatabase:^(FMDatabase *_dataBase){ 
     isOK = [_dataBase executeUpdate:sql withVAList:args]; 
    }]; 
    return isOK; 
} 
参照コード(インスピレーション):

FMDBクラスライブラリ関数のexecuteQuery

- (FMResultSet *)executeQuery:(NSString*)sql, ... { 
    va_list args; 
    va_start(args, sql); 

    id result = [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args]; 

    va_end(args); 
    return result; 
} 
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args { 
    //xxx 
} 
関連する問題