簡體   English   中英

在AppDelegate中的reloadData之后未調用cellForRowAtIndexPath

[英]cellForRowAtIndexPath not called after reloadData in AppDelegate

我已經搜索了幾個小時,盡管有很多類似的帖子,但找不到任何解決我的問題的方法。 我正在創建一個應用程序,該應用程序(從現在開始)正在使用startMonitoringSignificantLocationChanges不斷更新用戶位置。 我有一個自定義的viewcontroller LocationsViewController ,它只是一個表視圖,用於顯示用戶前往的每個位置。 在我的didUpdateLocations

- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    _currentLocation = _locationManager.location;
    [_locations addObject:_currentLocation];
    [_locationsViewController.tableView reloadData];
}

然后在LocationsViewController的numberOfRowsInSection方法中,我有以下代碼:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    AppDelegate * delegate = [AppDelegate sharedInstance];
    NSLog(@"%lu", (unsigned long)[delegate.locations count]);
    return [delegate.locations count];
}

現在,我在AppDelegate實例化了LocationsViewController ,如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    sharedInstance              = self;
    _datahub                    = [[Datahub alloc] init];
    _locations                  = [[NSMutableArray alloc] init];
    _locationManager            = [[CLLocationManager alloc] init];
    _locationManager.delegate   = self;

    UIStoryboard * storyboard   = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    _locationsViewController    = (LocationsViewController*) [storyboard instantiateViewControllerWithIdentifier:@"locationsViewController"];
    _timePickViewController     =  (TimePickViewController*) [storyboard instantiateViewControllerWithIdentifier:@"timePickViewController"];


    if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
        [_locationManager requestAlwaysAuthorization];
    }

    [_locationManager startMonitoringSignificantLocationChanges];
    return YES;
}

LocationsViewControllernumberOfRowsInSection方法中,首次實例化LocationsViewController時, delegate.locations numberOfRowsInSection的計數為0。 但是,在didUpdateLocations之后,將使用1個位置填充數組delegate.locations didUpdateLocations 然后,調用reloadData方法,並再次調用numberOfRowsInSection時,它返回1。如果該方法返回1,則應cellForRowAtIndexPath其后調用cellForRowAtIndexPath否則,將立即調用cellForRowAtIndexPath 但是由於某種原因,它沒有被調用。 我想知道是否有人知道1.我的代碼可能有什么問題(因為我使用情節提要,所以我認為它與任何格式或表格視圖設置無關),我的dataSourcedelegate都設置為self.tableView ,我還嘗試實現heightForRowAtIndexPath方法。 無論我做什么,我都沒有運氣。 調用reloadData ,將調用所有正確的方法,但cellForRowAtIndexPath除外。 任何建議或導致錯誤之處的建議都會很棒。 如果有幫助,這里還有更多代碼,謝謝:LocationsViewController.m

@implementation LocationsViewController
//*******************************************************************************************************************************
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.delegate            = self;
    self.tableView.dataSource          = self;


}
//*******************************************************************************************************************************
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
//*******************************************************************************************************************************
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 30.0f;
}
//*******************************************************************************************************************************
#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
//*******************************************************************************************************************************
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    AppDelegate * delegate = [AppDelegate sharedInstance];
    NSLog(@"%lu", (unsigned long)[delegate.locations count]);
    return [delegate.locations count];
}
//*******************************************************************************************************************************
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //Cell setup
    AppDelegate * delegate = [AppDelegate sharedInstance];

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                      reuseIdentifier:CellIdentifier];
    }

    //Edit cell
    CLGeocoder *ceo = [[CLGeocoder alloc]init];

    CLLocation * location = delegate.locations[indexPath.row];

    [ceo reverseGeocodeLocation:location
              completionHandler:^(NSArray * placemarks, NSError *error) {
                  CLPlacemark *placemark = [placemarks objectAtIndex:0];
                  //String to hold address
                  cell.textLabel.text = [NSString stringWithFormat:@"%F, %F", location.coordinate.latitude, location.coordinate.longitude];
                  cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@", placemark.locality, placemark.administrativeArea];
              }
     ];

    return cell;
}

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    sharedInstance              = self;
    _datahub                    = [[Datahub alloc] init];
    _locations                  = [[NSMutableArray alloc] init];
    _locationManager            = [[CLLocationManager alloc] init];
    _locationManager.delegate   = self;

    UIStoryboard * storyboard   = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    _locationsViewController    = (LocationsViewController*) [storyboard instantiateViewControllerWithIdentifier:@"locationsViewController"];
    _timePickViewController     =  (TimePickViewController*) [storyboard instantiateViewControllerWithIdentifier:@"timePickViewController"];


    if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
        [_locationManager requestAlwaysAuthorization];
    }

    [_locationManager startMonitoringSignificantLocationChanges];
    return YES;
}
//*******************************************************************************************************************************
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    _currentLocation = _locationManager.location;
    [_locations addObject:_currentLocation];
    [_locationsViewController.tableView reloadData];
}

@rdelmar的評論是問題的核心。 在您的應用程序委托中,您要實例化LocationsViewController,然后再對其執行任何操作。 該視圖控制器將永遠不會出現在屏幕上,也永遠不會做任何事情。

通常,讓應用程序委托管理除初始設置和處理應用程序委托方法以外的任何事情都是很糟糕的。 您應該使視圖控制器創建一個位置管理器對象,或者設置一個單獨的位置服務對象來執行此操作。

直接進入視圖控制器並直接操縱其視圖對象也是一個非常糟糕的主意。 如果您需要一個視圖控制器來更新其中一個視圖,則應添加一個外部對象調用的方法,該方法將根據需要更改視圖。

盡管有局限性,但使視圖控制器管理位置管理器本身是最簡單的解決方案。 僅當該視圖控制器關心位置服務時,該方法才有效。

如果您的應用中還有其他關心位置信息的對象(視圖控制器等),則應創建一個單獨的對象來管理位置更新。 在這種情況下,您應該為它設置一個委托,或者給它一個位置更新塊,以便在有可用更新時調用。 如果您希望同時通知應用程序中的多個視圖控制器,則可能要使用通知管理器發出自定義位置更新通知。

您可能希望使位置服務對象成為單例對象。 這樣,您的視圖控制器就可以獲取位置服務對象的單個實例,並將其設置為deleate /將它們的處理程序塊設置為最前面的活動處理程序塊。

暫無
暫無

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

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