首先說明一下題目中的形如部分(NSError *__autoreleasing *),這部分可能剛開始看有點兒理解不了,其實就是這樣的(NSError **),這就表示一個指向指針的指針,__autoreleasing是一個修飾符,表示傳入的是一個經過autorelease方法返回的id對象,這在內存管理中用到的。函數
咱們都知道這樣一個問題,將一個基本數據類型的變量經過函數參數傳入函數內,在函數內如何改變,都不會影響到外部變量的值!以下代碼:指針
#import <Foundation/Foundation.h> void test(int a) { a = 10; } int main(int argc, const char * argv[]) { @autoreleasepool { int a = 5; test(a); NSLog(@"a = %i", a); } return 0; }
a的值仍是等於5,說明函數傳遞的只是一個5的值。那若是要在函數內部改變外部變量的值要怎麼辦呢?固然是用指針了,將指針的值傳入函數,而後在函數中根據指針去找到指向的內存中修改,代碼以下:code
#import <Foundation/Foundation.h> void test(int * a) { *a = 10; } int main(int argc, const char * argv[]) { @autoreleasepool { int a = 5; test(&a); NSLog(@"a = %i", a); } return 0; }
這時a的值是10了,咱們傳入的是內存地址,而後在函數中對地址指向內存進行修改。對象
那麼,若是函數參數自己是一個對象,咱們傳入的是一個對象,自己就是一個地址,會怎樣呢?咱們先新建一個對象MyObject,而後有一個NSString類型的name屬性,這個代碼我就不貼出來了,直接看main.m的代碼吧!內存
#import <Foundation/Foundation.h> #import "MyObject.h" void test(MyObject * obj) { obj.name = @"XCoder Studio"; obj = [[MyObject alloc] init]; obj.name = @"Web Site"; } int main(int argc, const char * argv[]) { @autoreleasepool { MyObject * obj = [[MyObject alloc] init]; obj.name = @"XCoder"; test(obj); NSLog(@"obj.name = %@", obj.name); } return 0; }
怎麼樣,輸出結果是XCoder Studio,而不是Web Site。由於咱們傳入函數的是obj這個指針,這個指針指向了內存中的一個MyObject對象,函數中obj.name改變的是這個對象的屬性,當函數中obj = [[MyObject alloc] init];執行後,系統會在內存中新開闢一起存儲空間存儲一個新的MyObject對象,而後將函數中的obj存儲的指針值改成這個新的內存地址,而函數外的obj指針並無改變,仍是指向原來的這個對象的地址。it
那麼咱們如何實如今函數中改變函數外對象呢?就用一個新的指針指向這個對象的指針,也就是咱們說的指向指針的指針。代碼以下:內存管理
#import <Foundation/Foundation.h> #import "MyObject.h" void test(MyObject ** obj) { *obj = [[MyObject alloc] init]; (*obj).name = @"Web Site"; } int main(int argc, const char * argv[]) { @autoreleasepool { MyObject * obj = [[MyObject alloc] init]; obj.name = @"XCoder"; test(&obj); NSLog(@"obj.name = %@", obj.name); } return 0; }
這時候就實現了吧!io
標題中所說的NSError *__autoreleasing *都是這樣的,咱們能夠在外面新建一個NSError,當函數運行中有錯誤時,新建一個NSError對象並存儲到咱們新建的這個NSError對象中。咱們就能夠經過這個NSError是否爲nil看函數運行是否出錯!test