0

私は2つのクラスを持っていMPRequestますMPModel. このMPModelクラスには、コア データ ストアから何かを検索するメソッドがあり、見つからない場合はMPRequest、標準の HTTP 要求を介してそれを取得するための を作成します (のメソッドMPModelは静的であり、インスタンス メソッドではありません)。

私が望むのは、現在の HTTP リクエストの進行状況を取得できるようにすることです。これを行う方法は知っていますが、View Controllerに通知する方法に少し行き詰まっています。プロトコルを作成し、MPRequestクラスでデリゲート プロパティを定義しMPModel、このデリゲートを受け入れるようにメソッドを変更し、作成時に に渡してみMPRequestました。

これは問題ありませんが、ARC はリクエストの実行中にこのデリゲートを解放しているため、私が望むことを行いません。参照サイクルがスローされる場合に備えて、デリゲート オブジェクトを強い参照にしないようにしていますが、これを行う他の方法がわかりません。

リクエストを開始するには、実行しているView Controllerから

[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、応答の予想されるサイズを格納するだけです。

4

1 に答える 1

0

動作しました。コア データ スレッドがリクエストの前に終了していたスレッド化の問題、別のリクエストからの出力全体、および ARC がブロック単位でメモリを処理する方法に問題がありました。

助けてくれてありがとう

于 2013-01-08T23:36:25.140 に答える