我有 2 节课,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];
在这里,由于明显的原因, 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
存储响应的预期大小。