4

我想使用將指針指向NSError對象作爲參數的方法來創建NSInvocation對象。這方面的一個例子是方法 -如何使用將指針指向對象的方法作爲參數來創建NSInvocation對象

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr 

我undersand,我會爲我設置調用像這樣

NSData *myData = [[NSData alloc] init]; 

SEL writeToFileSelector = @selector(writeToFile:options:error:); 
NSMethodSignature *signature = [NSData instanceMethodSignatureForSelector:writeToFileSelector]; 

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 
[invocation setTarget:myData]; 
[invocation setSelector:writeToFileSelector]; 

NSString *string = [NSString stringWithFormat:@"long cat"]; 
NSDataWritingOptions *dataOptions; 
*dataOptions = NSDataWritingFileProtectionComplete; 

[invocation setArgument:&string atIndex:2]; 
[invocation setArgument:&dataOptions atIndex:3]; 

對於將writeToFile:選項:錯誤:最後一個參數期望接收的指針而不是一個對象。其結果是執行以下操作不起作用 -

NSError *err = nil; 
[invocation setArgument:&err atIndex:4]; 

這似乎是合乎邏輯的解決方案可能是創建一個指針的指針,但這會導致編譯器警告。我不知道如何正確執行,不會造成內存管理問題。

回答

3

您創建的參數與您傳遞給該方法的任何其他參數相同。

正如你指出的那樣,方法簽名需要一個NSError **作爲它的最後一個參數(索引4)。所以,你需要聲明一個,但是有一點困難。

NSError **errorPointer

爲您提供了一個指向NSError可變的變量。但是,既然你沒有告訴它指向任何變量,它指向零。因此,當您啓動調用時,選擇器將無法更改錯誤指針指向的變量。換句話說,這就像打電話[myData writeToFile:string options:dataOptions error:NULL]

所以,你要還聲明NSError變量,並指定其地址作爲errorPointer應指向變量:

NSError *error; 
NSError **errorPointer = &error; 

現在你可以在errorPointer作爲參數傳遞,和你如果調用方法時出現問題,稍後可以檢查它。查看this post on NSInvocation獲得更多幫助(帽子提示Mark Dalrymple指出博客帖子)

重要的是還要認識到,應該爲您創建的參數考慮範圍並將其傳遞到您的調用中。看看我問here的類似問題。

+2

「但是,既然你沒有告訴它指向任何變量,它指向零。」什麼?不,它沒有定義 – user102008 2012-05-11 18:49:25

+0

「現在你可以傳入errorPointer作爲參數」你不解釋如何傳遞它。 – user102008 2012-05-11 18:50:13

+2

#1在ARC下,未分配的本地指針變量被自動設置爲零。在C或非ARC Obj-C中,你是正確的。 #2傳遞errorPointer作爲第四個參數'[invocation setArgument:&errorPointer atIndex:4]' – edelaney05 2012-05-11 21:22:07

0

參數類型爲NSError **,您可以從要獲得錯誤信息的NSError *的地址獲取該參數。要在NSInvocation中設置參數,您需要將參數值的地址傳遞給setArgument:,因此您需要將NSError **放入一個變量中(我在此稱其爲errPointer),並將其地址(將會是NSError ***)傳遞給setArgument:。之後您不需要errPointer變量。

NSError *err = nil; 
NSError **errPointer = &err; 
[invocation setArgument:&errPointer atIndex:4]; 
2

edelaney05接受的答案很好,但我認爲它需要對ARC進行一些微調。 (我不能添加評論,所以創建一個新的答案記錄我發現了什麼)

原樣,我得到的編譯錯誤: 「指向非const類型‘NSError *’沒有明確的所有權「

我研究這個,我發現我需要:

NSError * __autoreleasing error = nil; 
NSError * __autoreleasing *errorPointer = &error; 

引用,導致我這樣的回答:

NSInvocation & NSError - __autoreleasing & memory crasher

Automatic Reference Counting: Pointer to non-const type 'NSError *' with no explicit ownership

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

「__autoreleasing被用於表示通過引用傳遞(ID *)和返回時被自動釋放參數」。

相關問題