我有两个课程,MPRequest
和MPModel
。
MPModel
类有一个从核心数据存储中查找内容的方法,如果没有找到,则创建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];
在这里,由于显而易见的原因,自我永远不会被释放,所以我不知道这是怎么回事。
上面,MPPlace
是MPModel
的子类,但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
。
答案 0 :(得分:0)
搞定了。这部分是线程问题,核心数据线程在我的请求之前结束,我完全从不同的请求查看输出,以及ARC处理块中的内存的方式。
感谢帮助人员