简体   繁体   English

EXC_BAD_ACCESS objective-c块

[英]EXC_BAD_ACCESS objective-c block

I run this code inside my viewDidLoad method to fetch data from Firebase to put it in a UIPageViewController 我在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];
        }
    }];


}

And this is the called setRoutes method: 这就是所谓的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];
}

When the setRoutes method gets executed it throws the error in the image below, saying that it cannot dereference it: setRoutes方法被执行时,它会在下面的图像中抛出错误,说它无法取消引用它:

在此输入图像描述

The setRoutes methods gets executed inside a block. setRoutes方法在块内执行。

And I get this weird thread stack: 我得到这个奇怪的线程堆栈: 在此输入图像描述

How can I solve this? 我怎么解决这个问题?

Your problem is here: 你的问题在这里:

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

invoking self.routes implicity calles the setter setRoutes which causes a recursive infinite calls as indicated by your stack. 调用self.routes implicity会调用setter setRoutes ,它会导致堆栈指示的递归无限调用。

At the time the block is passed onto getDocumentsWithCompletion method is executed, routes array has already been deallocated and set to nil because no one is retaining it anywhere outside the block. 在将块传递给getDocumentsWithCompletion方法执行时, routes数组已经被释放并设置为nil因为没有人将它保留在块外的任何地方。

You should either move it into the block or declare it as a class property so it won't be thrown out of memory while class instance is alive. 您应该将其移动到块中或将其声明为类属性,以便在类实例处于活动状态时不会将其抛出内存。

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

After the update: 更新后:

Doing self.routes = routes invokes setRoutes: which in turn is causing a loop in your code. 执行self.routes = routes调用setRoutes:这反过来导致代码中的循环。 You should change it to: 您应该将其更改为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM