阻止和保留循环无法捕获它

时间:2012-11-13 13:34:21

标签: ios block weak-references retain-cycle


我遇到了块和弱引用的问题,我在ARC下。我构建了一个类,它是一个免费项目,是一种围绕Google Directions API的简单包装,您可以在此处下载:link to the project
我在视图控制器中使用它的问题是在使用它之后视图控制器没有被释放。我想这是这个对象的问题,因为如果我将它注释掉或设置为nil一切正常。我无法理解保留周期在哪里,当然我设置为弱自我,这里是我使用它的视图控制器的方法:

- (void) getDirections{
 __weak RouteMapViewController *  weakSelf =  self;
self.routeObject = [[RouteDirectionsObject alloc]init];

[self.mapView removeAnnotations:self.mapView.annotations];
[self.mapView removeOverlays:self.mapView.overlays];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[_routeObject createDirectionRequestWithStartPoint:weakSelf.startPoint
                                           andEndPoint:weakSelf.endPoint
                                     withCallBackBlock:^(NSError *error, NSDictionary *routeDistance, NSDictionary *routeDuration, MKPolyline *routePolyline, NSArray *routes, NSArray *steps, CLLocation *startPoint, CLLocation *endPoint, NSArray *directions) {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    Annotation * startAnnotation = [[Annotation alloc]initWithCoordinate:startPoint.coordinate title:NSLocalizedString(@"YOUR_POSITION_KEY", @"Your position") annotationType:AnnotationTypeStart];
    Annotation * endAnnotation = [[Annotation alloc]initWithCoordinate:endPoint.coordinate title:NSLocalizedString(@"AIRPORT_POSITION_KEY", @"Airport position") annotationType:AnnotationTypeEnd];
    NSArray * annotationArray = [NSArray arrayWithObjects:startAnnotation, endAnnotation, nil];
    weakSelf.routeSteps = steps;
    weakSelf.routeDirections = directions;
    weakSelf.duration = routeDuration;
    weakSelf.distance = routeDistance;
    CLLocationDegrees maxLat = -90.0f;
    CLLocationDegrees maxLon = -180.0f;
    CLLocationDegrees minLat = 90.0f;
    CLLocationDegrees minLon = 180.0f;

    for (int i = 0; i < weakSelf.routeSteps.count; i++) {
        NSDictionary * stepDictCoordinate = [[weakSelf.routeSteps objectAtIndex: i]objectForKey:@"start_location"];
        CLLocationCoordinate2D currentLocationCoordinate = CLLocationCoordinate2DMake([[stepDictCoordinate objectForKey:@"lat"]doubleValue], [[stepDictCoordinate objectForKey:@"lng"]doubleValue]);
        if(currentLocationCoordinate.latitude > maxLat) {
            maxLat = currentLocationCoordinate.latitude;
        }
        if(currentLocationCoordinate.latitude < minLat) {
            minLat = currentLocationCoordinate.latitude;
        }
        if(currentLocationCoordinate.longitude > maxLon) {
            maxLon = currentLocationCoordinate.longitude;
        }
        if(currentLocationCoordinate.longitude < minLon) {
            minLon = currentLocationCoordinate.longitude;
        }
    }

    MKCoordinateRegion region;
    region.center.latitude     = (maxLat + minLat) / 2;
    region.center.longitude    = (maxLon + minLon) / 2;
    region.span.latitudeDelta  = maxLat - minLat;
    region.span.longitudeDelta = maxLon - minLon;


    dispatch_async(dispatch_get_main_queue(), ^{
        if ( error) {
            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Error", @"Error alert view title") message:NSLocalizedString(@"KEY_DIRECTIONS_ERROR", @"Alert error message for directions") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];

            [_routesButton setEnabled:NO];

        }
        else{
            [weakSelf.mapView addAnnotations:annotationArray];
            [_routesButton setEnabled:YES];

            if(routePolyline){
                [weakSelf.mapView addOverlay:routePolyline];
            }
            else{
                UIAlertView * alert = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Error", @"Error alert view title") message:NSLocalizedString(@"KEY_DIRECTIONS_POLYLINE_ERROR", @"Polyline inconsistant") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
                [alert show];

            }
            //[weakSelf.mapView setRegion:region animated:YES];
            [weakSelf setRegion:region];
        }
    });
}];}

如果我放置断点并询问视图控制器的retainCount,我可以看到即使视图控制器传递的设置为弱,它也会增加不同的时间。 任何帮助将非常感谢 谢谢,
安德烈

/ * ** * ** * ** * ** 更新 * ** * ** * ** * 的* / **
使用分配进行检查我可以看到,在块内部,视图控制器被保留很多次,通过一个名为-tryRetain的方法直到递减但似乎错过了一个释放来释放。 为了清楚起见,我必须指定传递的块被复制到类路由方向对象中。 我做了一个小样本,你可以在这里下载:download project

3 个答案:

答案 0 :(得分:1)

对象的绝对保留计数毫无意义; www.whentouseretaincount.com(底部有一些描述技术细节的链接)。

Leaks仪器不太可能有所帮助。它可能,但也许不是。但是,分配工具是你的朋友。打开“记录引用计数”和“仅跟踪活动分配”。在仪器中运行您的应用程序,然后查找应该消失的对象,但不是。单击任何一个将显示该对象的保留/释放事件,该事件将回答额外保留来自何处的问题。

更可能的是,鉴于这是一个视图对象,这是因为它仍然在视图层次结构中,但是隐藏在其他不透明的视图之后。它也可以作为计时器或缓存的目标,可能是“返回”式导航缓存。

答案 1 :(得分:0)

您可以使用仪器来确定保留和释放物体的内容,并找出不平衡发生的位置。这可以通过在构建和运行项目时选择Profile来完成,然后启动仪器。

进入后,您可以选择泄漏来确定泄漏发生的位置。 enter image description here

您可以用来掌握乐器的几个指南:

答案 2 :(得分:-1)

您不应该使用自我类的实例变量(在块中),在您的情况下使用_routerButton