使用ARC将委托传递给另一个对象

时间:2012-12-13 01:40:32

标签: objective-c ios cocoa-touch delegates

我有两个课程,MPRequestMPModelMPModel类有一个从核心数据存储中查找内容的方法,如果没有找到,则创建MPRequest以通过标准HTTP请求检索它(MPModel中的方法是静态的而不是和实例方法)。

我想要的是能够获得当前HTTP请求的进度。我知道如何做到这一点,但我对如何通知视图控制器有点困惑。我尝试创建一个协议,在MPRequest类中定义委托属性,在MPModel中更改方法以接受此委托,然后在创建时将其传递给MPRequest

这很好,但是ARC在请求运行时释放了这个委托,因此没有按照我的意愿行事。我试图避免使我的委托对象成为一个强大的引用,以防它引发任何引用周期但我不知道其他任何方式这样做。

要启动请求,请从我的视图控制器运行

[MPModel findAllWithBlock:^(NSFetchedResultsController *controller, NSError *error) {
    ....
} sortedBy:@"name" ascending:YES delegate:self]

在findAllWithBlock方法中,我有

MPRequest *objRequest = [MPRequest requestWithURL:url];
  objRequest.delegate = delegate;

[objRequest setRequestMethod:@"GET"];
[MPUser signRequest:objRequest];

[objRequest submit:^(MPResponse *resp, NSError *err) {
    ...
}

MPRequest课程中,我定义了以下属性:

@property (nonatomic, weak) NSObject<MPRequestDelegate> *delegate;

有任何想法或建议吗?

根据要求,这里有一些关于如何调用事物的代码:

在视图控制器中:

[MPPlace findAllWithBlock:^(NSFetchedResultsController *controller, NSError *error) {
        _placesController = controller;
        [_listView reloadData];
        [self addAnnotationsToMap];
        [_loadingView stopAnimating];

        if (_placesController.fetchedObjects.count > 0) {
            // We've got our places, but if they're local copies
            // only, new ones may have been added so just update
            // our copy
            MPSyncEngine *engine = [[MPSyncEngine alloc] initWithClass:[MPPlace class]];
                 engine.delegate = self;
            [engine isReadyToSync:YES];
            [[MPSyncManager sharedSyncManager] registerSyncEngine:engine];
            [[MPSyncManager sharedSyncManager] sync];
        }
    } sortedBy:@"name" ascending:YES delegate:self];

在这里,由于显而易见的原因,自我永远不会被释放,所以我不知道这是怎么回事。

上面,MPPlaceMPModel的子类,但findAllWithBlock:sortedBy:ascending:delegate:的实现完全在MPModel

MPModel中的方法如下所示

NSManagedObjectContext *context = [[MPCoreDataManager sharedInstance] managedObjectContext];
[context performBlockAndWait:^{
    __block NSError *error;
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([self class])];
    [request setSortDescriptors:@[[[NSSortDescriptor alloc] initWithKey:key ascending:asc]]];

    NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                                 managedObjectContext:context
                                                                                   sectionNameKeyPath:nil
                                                                                            cacheName:nil];

    [controller performFetch:&error];

    if (!controller.fetchedObjects || controller.fetchedObjects.count == 0) {
        // Nothing found or an error, query the server instead
                NSString *url = [NSString stringWithFormat:@"%@%@", kMP_BASE_API_URL, [self baseURL]];
        MPRequest *objRequest = [MPRequest requestWithURL:url];
          objRequest.delegate = delegate;

        [objRequest setRequestMethod:@"GET"];
        [MPUser signRequest:objRequest];

        [objRequest submit:^(MPResponse *resp, NSError *err) {
            if (err) {
                block(nil, err);
            } else {
                NSArray *objects = [self createListWithResponse:resp];
                         objects = [MPModel saveAllLocally:objects forEntityName:NSStringFromClass([self class])];
                [controller performFetch:&error];
                block(controller, nil);
            }
        }];
    } else {
        // Great, we found something :)
        block (controller, nil);
    }
}];

委托只是被传递给正在创建的MPRequest对象。我最初担心的是创建的MPRequest对象是由ARC发布的(我猜它可能是这样)但是当我更改它时它没有修复任何东西。我不能把它变成iVar,因为这个方法是静态的。

请求的提交方法如下所示:

_completionBlock = block;
   _responseData = [[NSMutableData alloc] init];

[self prepareRequest];

[self prepareRequestHeaders];
_connection = [[NSURLConnection alloc] initWithRequest:_urlRequest
                                              delegate:self];

当应用程序开始下载数据时,它会调用:

[_responseData appendData:data];
[_delegate requestDidReceive:(float)data.length ofTotal:_contentLength];

其中_contentLength只是一个存储预期响应大小的long

1 个答案:

答案 0 :(得分:0)

搞定了。这部分是线程问题,核心数据线程在我的请求之前结束,我完全从不同的请求查看输出,以及ARC处理块中的内存的方式。

感谢帮助人员