簡體   English   中英

ARC中的虛假va_list

[英]fake va_list in ARC

我需要在iOS應用程序中創建一個偽va_list來傳遞給NSString initWithFormat:arguments: function,這是我的代碼:

NSArray *fixedArguments = [[NSArray alloc] initWithArray:arguments]; 

NSRange range = NSMakeRange(0, [fixedArguments count]);

va_list fakeArgList = (va_list)malloc(sizeof(NSString *) * [fixedArguments count]);

__unsafe_unretained id *ptr = (__unsafe_unretained id *)fakeArgList;

[fixedArguments getObjects:ptr range:range];

content = [[NSString alloc] initWithFormat:outputFormat
                                            arguments:(va_list)fakeArgList];
free(fakeArgList);

編譯器在轉換線上抱怨此消息:

error: cast of a non-Objective-C pointer type 'va_list' (aka 'char *') to '__unsafe_unretained id *' is disallowed with ARC

getObjects:range:函數定義如下:

- (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range;

我已經嘗試了一切,但仍然無法擺脫這個錯誤......

是否有創建啟用ARC的虛假va_list的解決方案? 我究竟做錯了什么?

編輯:這不再有效。 正如在最初的答案中所預見的那樣,ABI似乎已經從這個答案中改變了

玩了一下並讓它工作 - 雙重檢查泄漏或遺棄的記憶,沒有看到任何。

    NSArray *fixedArguments = [[NSArray alloc] initWithObjects: @"foo", @"bar", @"baz", nil]; 

    NSRange range = NSMakeRange(0, [fixedArguments count]);

    NSMutableData* data = [NSMutableData dataWithLength: sizeof(id) * [fixedArguments count]];    

    [fixedArguments getObjects: (__unsafe_unretained id *)data.mutableBytes range:range];

    NSString* content = [[NSString alloc] initWithFormat: @"1: %@ 2: %@ 3: %@"  arguments: data.mutableBytes];

    NSLog(@"%@", content);

我喜歡(ab)像這樣使用NSMutableData來獲取任意內存塊上的保留/釋放語義 - 它不一定與手頭的問題有關,但它是一個巧妙的小技巧。

作為對未來讀者的一個注意事項:假裝這樣的va_list恰好適用於當前的MacOS和iOS ABI,但總的來說它不是便攜式的,也不是一個好方法。

如果您願意為您的項目添加一點點快速,那么它是可能的!

重要的是NSArray到[CVarArgType]的映射,它是va_list的快速等價物。 如果您嘗試將[AnyObject][CVarArgType]則會導致運行時崩潰,但是使用map我們可以顯式創建所需的列表。

代碼的其余部分是我制作的包裝器,以便我可以從obj-c調用它。 您可以為要以這種方式調用的任何obj-c函數創建包裝器。

@objc class StringFormat: NSObject {
    class func format(key: String, args: [AnyObject]) -> String {
        let locArgs: [CVarArgType] = args.map({ (arg: AnyObject) -> CVarArgType in
            if let iArg = (arg is NSNumber ? arg.intValue : nil) {
                return iArg
            }
            return arg as! CVarArgType
        });
        return String(format: key, arguments: locArgs)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM