【问题标题】:EXC_BAD_ACCESS objective-c blockEXC_BAD_ACCESS 目标-c 块
【发布时间】:2017-12-21 15:18:17
【问题描述】:

我在我的 viewDidLoad 方法中运行此代码以从 Firebase 获取数据并将其放入 UIPageViewController

@interface MapViewController () <RoutesPageDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (weak, nonatomic) RoutesPageViewController *routesPageViewController;
@property (weak, nonatomic) FIRFirestore *db;
@end

@implementation MapViewController

- (void) viewDidLoad {
    [super viewDidLoad];

    self.db = [FIRFirestore firestore];

    for (UIViewController *obj in self.childViewControllers) {
        if ([obj isKindOfClass:[RoutesPageViewController class]]) {
            self.routesPageViewController = (RoutesPageViewController *)obj;
            self.routesPageViewController.routesPageDelegate = self;
        }
    }

    FIRCollectionReference *routesRef = [self.db collectionWithPath:@"routes"];
    [routesRef getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
        if (error != nil) {
            // TODO: handle error
        } else {
            NSMutableArray<RouteModel*> *routes = [NSMutableArray array];

            // For each route
            for (FIRDocumentSnapshot *document in snapshot.documents) {
                RouteModel *route = [[RouteModel alloc] init];
                route.title = document.data[@"title"];
                route.color = document.data[@"color"];
                route.city = document.data[@"city"];

                [routes addObject:route];
            }

            [self.routesPageViewController setRoutes:routes];
        }
    }];


}

这就是调用的 setRoutes 方法:

- (void) setRoutes:(NSMutableArray<RouteModel *> *)routes {
    self.routes = routes;

    NSMutableArray<RoutePageViewController *> * routeViewControllers = [NSMutableArray array];
    for (RouteModel * route in routes) {
        [routeViewControllers addObject:[self viewControllerAtIndex:[routes indexOfObject:route]]];
    }

    [self setViewControllers:routeViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}

setRoutes 方法被执行时,它会抛出下图中的错误,说它不能取消引用它:

setRoutes 方法在块内执行。

我得到了这个奇怪的线程堆栈:

我该如何解决这个问题?

【问题讨论】:

  • 你在哪里创建 routesPageViewController?这个属性是怎么定义的?
  • viewDidLoad 方法中我将它分配给一个弱的非原子属性

标签: ios objective-c firebase block


【解决方案1】:

你的问题在这里:

- (void) setRoutes:(NSMutableArray<RouteModel *> *)routes {
    self.routes = routes;

调用self.routes 隐式调用设置器setRoutes,这会导致递归无限调用,如您的堆栈所示。

【讨论】:

  • Tnx。这解决了问题。但我现在有一个新的。 ` '提供的视图控制器数量 (2) 与请求的转换所需的数量 (1) 不匹配'`
  • 表示页面视图控制器只需要一个视图控制器,其他视图控制器必须使用页面视图控制器的数据源机制添加
  • 我已经实现了
  • 好的,所以现在你需要做的就是只在数组中传递将显示的第一个视图控制器。您需要在数据源的pageViewController:viewControllerBeforeViewController:pageViewController:viewControllerAfterViewController: 方法中提供的其他视图控制器
【解决方案2】:

在将块传递给getDocumentsWithCompletion 方法执行时,routes 数组已经被释放并设置为nil,因为没有人将它保留在块之外的任何地方。

您应该将它移动到块中或将其声明为类属性,这样它就不会在类实例处于活动状态时被抛出内存。

[routesRef getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
    NSMutableArray<RouteModel*> *routes = [NSMutableArray array];
    ...
    [self.routesPageViewController setRoutes:routes];
}];

更新后:

执行self.routes = routes 会调用setRoutes:,这反过来又会导致您的代码出现循环。您应该将其更改为:

- (void)setRoutes:(NSMutableArray<RouteModel *> *)routes {
  if (_routes != routes) {
    _routes = routes;
    ...
  }
}

【讨论】:

  • routes 不能是 nil 如果你按照我的建议去做。应用程序可能由于不同的错误而崩溃。也许您可能想分享更多代码?
  • 我编辑了这个问题。在setRoutes 方法中接收时为 nil
  • @TheoBouwman 不一定。崩溃发生在方法签名行上,这意味着整个视图控制器已被释放,您仍然尝试访问它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多