繁体   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