2013-12-24 22 views
0

在過去的2個小時中,我一直在努力實現CLGeocoder類方法,該方法用於地理位置的反向地理編碼。對CLGeocoder類方法進行反向地理編碼的方法感到困惑

被設置用於下CLGeocode類參考Xcode文檔中此方法的代碼是這樣的:

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler 

我試圖用在我的代碼,並沒有任何運氣。所以我查看了一些舊的stackoverflow問題,發現一個實現最終爲我工作。

這是對我的作品的代碼:

-(IBAction)gpsButton { 

CLGeocoder *geocoder = [[CLGeocoder alloc]init]; 

[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error){ 

    CLPlacemark *placemark = placemarks[0]; 
    NSLog(@"Found %@", placemark.thoroughfare); 

} 

]; 

} 

我不明白的是爲什麼Xcode的文件包括(CLLocation *)和(CLGeocodeCompletionHandler)時,這不是真的是多麼的最終代碼需要看。

它只是試圖提醒我,「位置」對象應該是CLLocation類的實例,並且「completionHandler」對象應該是CLGeocodeCompletionHandler類的實例嗎?

是否試圖提醒我,在實現此方法之前,我需要爲CLLocation類和CLGeocodeCompletionHandler類創建和初始化對象,以便該方法可以正常工作?如果是這種情況,爲什麼CLLocation在xcode示例中有一個指針,但是CLGeocodeCompletionHandler不是?

我意識到這是一個「基本面」類型的問題,但我已經瀏覽了一些我的參考資料,他們解釋事物的方式真的沒有幫助我解決當前的困惑。

謝謝你的幫助。

回答

1

你說:

我不明白的是爲什麼Xcode的文件包括(CLLocation *)和(CLGeocodeCompletionHandler)時,這不是真正的最終代碼需要如何看。

事情是,這個最終的代碼看起來如何。因此,當你所指出的,reverseGeocodeLocation:completionHandler:方法被定義爲這樣:

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler; 

此外,如果你看的CLGeocodeCompletionHandler定義,它定義爲返回void和採用兩個參數的塊,標陣列和NSError對象,像這樣:

typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error); 

因此,您的代碼示例,下面,恰好符合這個定義:

[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error){ 

    CLPlacemark *placemark = placemarks[0]; 
    NSLog(@"Found %@", placemark.thoroughfare); 

}]; 

如果您問爲什麼reverseGeocodeLocation:completionHandler:的方法定義使用CLGeocodeCompletionHandler typedef而不是實際的複雜塊定義,他們會這樣做以簡化代碼。是的,它使Xcode的「代碼完成」沒有什麼幫助,但是當你實際上用block參數編寫實現這個方法的代碼時,它會讓你的生活變得更容易。

當你開始寫你自己的方法是拿塊參數和具有存儲在性能這些塊類,你會看到,使用typedef確實是一大福音,省去了很多來自於真正的錯別字導致簡單的錯誤尷尬的塊語法。

例如,假設你想保持在變量塊,然後使用該變量在您的來電reverseGeocodeLocation。因爲你有一個typedef,這是非常簡單的:

CLGeocodeCompletionHandler customHandler = ^(NSArray *placemarks, NSError *error){ 
    CLPlacemark *placemark = placemarks[0]; 
    NSLog(@"Found %@", placemark.thoroughfare); 
}; 

[geocoder reverseGeocodeLocation:currentLocation completionHandler:customHandler]; 

沒有的typedef,你不得不訴諸稍微笨拙的語法:

void (^customHandler)(NSArray *, NSError *) = ^void(NSArray *placemarks, NSError *error) { 
    CLPlacemark *placemark = placemarks[0]; 
    NSLog(@"Found %@", placemark.thoroughfare); 
}; 

[geocoder reverseGeocodeLocation:currentLocation completionHandler:customHandler]; 

這是無可否認的,有點做作例如,但是隨着越來越多地使用塊,您將開始欣賞當您不得不在整個代碼中一次又一次使用相同塊簽名時所提供的簡單性。

因此,無論何時您看到一個以自定義塊typedef作爲參數的方法,只需向下鑽取更多級別的細節,然後查看該typedef,並且所有方法都應該變得清晰。

+0

不可能是一個更完美的答案。謝謝! – user3117509

0

那麼CLLocation是你需要初始化和reverseGeocode的類,但CLGeocodeCompletionHandler是一個塊typedef句柄的回調。所以你不必初始化它。

+0

爲什麼我不需要初始化CLGeocodeCompletionHandler的原理是什麼?只是因爲它是一個typedef,因爲它是一個塊,因爲它是一個塊typedef? – user3117509

+2

塊是一個函數指針,而不是一個類。讀取[Block Guide](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/Blocks/Articles/00_Introduction.html#//apple_ref/ doc/uid/TP40007502-CH1-SW1) – johnMa

+0

簡而言之,Block是作爲變量傳遞的一段代碼。因此,而不是一個典型的方法說'用這個NSString做這個',你可以說'做點什麼,然後運行這個塊'。通常你可以輸入def塊來使它更易於引用(正如你可以從語法中看到的那樣,聲明一個塊在語法上是單調乏味的)。 –