2011-05-10 138 views
6

嗨我在iPhone上玩弄位置,從一開始就遇到問題。我已經本地化我的問題,並確定它是CLLocationManager這是困擾我。CLLocationManager從不調用委託方法

所以我開發了非常簡單的應用程序。我只有一個視圖控制器,裏面有一個CLLocationManager。在視圖上加載我初始化CLLocationManager並開始更新。我還實施了兩種方法didFailWithErrordidUpdateToLocation

我已經閱讀了很多問題,我學到的東西很多,所以這個價格是這樣的。在初始化期間,您必須保留CLLocationManager。此外,它是明智卸載的view過程中設置CLLocationManagersdelegatenil(一些與傳遞給CLLocationManager因爲框架保持它的消息做的,它從來沒有正確地釋放)

所有的一切我都無法找到什麼像樣的解釋如何使其工作。

這裏是我的代碼,所以如果有人可以弄明白,我將不勝感激。 viewControllers頭文件

#import <UIKit/UIKit.h> 
#import <CoreLocation/CoreLocation.h> 

@interface CoreLocationViewController : UIViewController <CLLocationManagerDelegate> 
{ 
    CLLocationManager *locManager; 
} 

@property (nonatomic, retain) CLLocationManager *locManager; 

@end 

的viewController .m文件

#import "CoreLocationViewController.h" 


@implementation CoreLocationViewController 
@synthesize locManager; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.locManager = [[CLLocationManager alloc] init]; 
    locManager.delegate = self; 
    [self.locManager startUpdatingLocation]; 

    self.view.backgroundColor = [UIColor grayColor]; 
} 

#pragma mark - 
#pragma mark Location Delegate 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{ 
     NSLog(@"in fail with error"); 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    NSLog(@"in update to location"); 
} 


#pragma mark - 
#pragma mark Memory Management 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (void)viewDidUnload 
{ 
self.locManager.delegate = nil; 
    [super viewDidUnload]; 
} 


- (void)dealloc 
{ 
    [locManager release]; 
     [super dealloc]; 
} 


@end 

BTW:我使用的是iOS 4.2。我指出這一點,因爲我讀的是蘋果已經改變了位置的代表在iOS 4的

+2

你在這裏泄漏,因爲self.locManager = [[CLLocationManager alloc] init];保留在使用alloc init獲得的引用計數之上的對象。 – logancautrell 2011-05-12 18:32:01

回答

3

所以我設法找到了一個錯誤。這是在內存管理。在我的應用程序委託文件中,我初始化了一個CoreLocationViewController,並將其作爲subview添加到我的窗口中,然後我釋放它,一切正常。但是,釋放部分並不是一個好的選擇。在我發佈我的ViewController後,dealloc方法被調用並釋放了locationManager

所以正確的做法是不要發佈ViewController,其中包含locationManager,或找到處理它的另一種方法。我不太清楚爲什麼這是一個問題,因爲我認爲在將一個ViewController添加到一個窗口後它會被保留,因此它的localtionManager也會被保留。如果有人能爲我清除它,將不勝感激。

+0

不可以。將視圖控制器的視圖添加到窗口後,它的VIEW將被保留,但不會保留視圖本身。這是一箇舊帖子,但仍值得評論。釋放屏幕上的視圖控制器可能會導致發生任何事情(如按鈕水龍頭)嘗試調用視圖控制器的其中一種方法時發生崩潰。 – 2013-11-17 15:14:58

0

IDK如果它是一個問題,但在我的代碼我還設置所需的精度

[locManager setDesiredAccuracy:kCLLocationAccuracyBest]。

例如。

2

您在設備上測試嗎?是否啓用位置服務?

if (self.locManager.locationServicesEnabled){ 
//do domething 
} 
+0

嘗試過..我用 'if([CLLocationManager locationServicesEnabled]) { \t [self.locManager startUpdatingLocation]; }' 但它沒有幫助。我認爲還有更多的東西 – paxx 2011-05-11 16:12:43

+0

corelocation框架肯定會添加到您的構建? – 2011-05-11 22:20:00

+1

是的..它不會運行沒有它 – paxx 2011-05-12 07:35:10

3

這可能是NIT挑剔,但在viewDidLoad中的變化:

locManager.delegate = self; 

到:

self.locManager.delegate = self; 

我不知道這是否會修復它,但最好要一致。

+1

tnx,但它沒有幫助.. – paxx 2011-05-11 16:16:15

+0

此修復適用於我。 – heMac 2013-04-30 18:58:24

0

試試這個:

NSLog(@"location services enabled: %d", [locManager locationServicesEnabled]); 

從文檔:

用戶可以通過切換在設置>通用>定位服務開關完全從設置應用程序啓用或禁用定位服務。

+0

試過..我用 'if([CLLocationManager locationServicesEnabled]) { \t [self.locManager startUpdatingLocation]; }' 但它沒有幫助。我認爲還有更多的東西 – paxx 2011-05-11 16:16:24

+0

NSLog聲明說了什麼?您的loc服務是否啓用?如果if語句被禁用,if語句將不會啓用它們 - 您必須在Settings應用程序中執行此操作。 – Rayfleck 2011-05-11 22:20:21

+0

服務啓用..但我在模擬器上運行,我不知道在模擬器上運行調用任何代表..我想它應該至少調用錯誤委託 – paxx 2011-05-12 07:36:11

4

其他海報提到檢查授權,你應該明確補充說,但我不認爲這是你的問題。如果您未被授權,您的didFailWithError:方法將被調用。這導致相信別的事情正在發生。

確保您的位置管理器確實正在分配,而您的位置管理器可以修復內存泄漏,這可能是一個好主意。

試試這個:

CLLocationManager* lm = [[CLLocationManager alloc] init]; 
NSAssert(lm != nil, @"Failed to allocate CLLocation manage"); 
self.locManager = lm; 
[lm release]; 
self.locManager.delegate = self; 
[self.locManager startUpdatingLocation]; 
// Let's just print what we got 
NSLog(@"CLLocationManager is %@", lm); 

如果您運行此您將得到以下結果之一:

1)如果位置管理器返回nil,你的程序會崩潰到調試器(因爲2)如果「CLLocationManager是...」打印出來,並且仍然沒有看到更新,那麼你手上就有一個真正的祕密。

3)沒有打印。這意味着,也許是由於在Interface Builder中錯誤地鏈接了某些內容,viewDidLoad根本沒有被調用。

4)您將得到一個didFailWithError:電話,因爲您沒有被授權。這意味着至少一切都按預期工作。

另外,由於您將alloc的結果直接分配給具有retain屬性的屬性,因此存在內存泄漏。在alloc之後,你的計數值在+1之後是+1,所以如果視圖被卸載並重新加載,你會泄漏。

希望這可以幫助一些。

+0

嘗試過..我有一個可疑的CLLocationManager是 ..我認爲還有更多的東西..也許我的電腦上的位置框架安裝不正確..你知道任何項目,或者你有和使用locationManager的項目和工作100%..我想測試如果它是我的代碼或可能是別的.. btw:tnx分配的東西..不知道..曾經是一個.NET編碼器,所以我仍然試圖適應沒有垃圾收集器環境 – paxx 2011-05-11 16:20:44

+0

我使用模擬器,因爲我沒有我自己的開發人員acc ..但我要去嘗試它在今天的朋友acc看看設備上會發生什麼..但我'米混淆在一件事..應該不是它至少在模擬器上調用一個錯誤委託?或者在模擬器上沒有任何事情發生是正常的? – paxx 2011-05-12 07:37:47

+0

@paki在我的4.2版本的模擬器中,它確實調用了正確的(儘管你只有幾個更新)。我不記得在早期版本中發生了什麼。 – idz 2011-05-12 07:52:52

0

我有同樣的問題,因爲paxx說,這是一個內存管理問題。我的解決方案是手動保留「自我」。如下面的代碼所示:

- (void) viewDidload 
{ 
    [super viewDidload]; 
    if (![CLLocationManager locationServicesEnabled]) { 
     NSLog(@"Location Service Disabled!"); 
    } else { 
     [self retain]; 
     //initialize the cllocationmanager obj. 
    } 
} 


-(void)locationManager:(CLLocationManager *)manager 
    didUpdateLocations:(NSArray *)locations 
{ 
    //do your surf 
    [self release]; 
} 


-(void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
      fromLocation:(CLLocation *)oldLocation 
{ 
    //do your stuff 
    [self release]; 
} 

-(void)locationManager:(CLLocationManager *)manager 
     didFailWithError:(NSError *)error 
{ 
    //do your stuff 
    [self release]; 
} 

不漂亮,但對我來說工作正常。

17

在我的情況下,委託不會被調用,因爲線程問題

  • 經營的LocationManager必須有一個NSRunLoop設置 了
  • 如果您使用主線程
  • 線程,你已經有runloop,現在你只需要 實例化管理器和使用它的主線程

Read this to know more about CLLocationManagerDelegate

+0

完美。爲我修好了。我早些時候已經嘗試了這一點,但只保證了'startUpdatingLocation'方法。實際上,alloc/init等也必須在主線程上! – 2013-11-13 23:32:48

+0

答案!在主線程的單獨隊列上實例化CLLocationManager是我的問題。將調用分派給主線程修復它。 – jcady 2016-01-19 20:26:53

+0

@TimBodeit這無疑爲我解決了這個問題。但我不明白的是以前我從'viewDidLoad'調用它。 viewDidLoad不是從主線程運行嗎? – Honey 2017-07-17 17:04:10

8

此外,在iOS8上必須有兩個額外的東西:

  • 從位置管理您的Info.plist並請求授權添加一個關鍵要求它開始。

    • NSLocationWhenInUseUsageDescription

    • NSLocationAlwaysUsageDescription

  • 您需要請求授權對相應的位置的方法。

    • [self.locationManager requestWhenInUseAuthorization]

    • [self.locationManager requestAlwaysAuthorization]

代碼例如:

self.locationManager = [[CLLocationManager alloc] init]; 
self.locationManager.delegate = self; 
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. 
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 
    [self.locationManager requestWhenInUseAuthorization]; 
} 
[self.locationManager startUpdatingLocation]; 

來源:http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

相關問題